forked from mirrors/linphone-iphone
Add file player
This commit is contained in:
parent
f548037fa2
commit
9a78e75722
4 changed files with 162 additions and 1 deletions
|
|
@ -163,6 +163,7 @@
|
|||
D7DA67622ACCB2FA00E95002 /* LoginFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */; };
|
||||
D7DA67642ACCB31700E95002 /* ProfileModeFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */; };
|
||||
D7E2E69F2CE356C90080DA0D /* PopupViewWithTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E2E69E2CE356C90080DA0D /* PopupViewWithTextField.swift */; };
|
||||
D7E2E6A12CE5F8850080DA0D /* QuickLookPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E2E6A02CE5F87D0080DA0D /* QuickLookPreview.swift */; };
|
||||
D7E6ADF32B9875C20009A2BC /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6ADF22B9875C20009A2BC /* Message.swift */; };
|
||||
D7E6ADF52B9876ED0009A2BC /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6ADF42B9876ED0009A2BC /* Attachment.swift */; };
|
||||
D7E6D0492AE933AD00A57AAF /* FavoriteContactsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D0482AE933AD00A57AAF /* FavoriteContactsListFragment.swift */; };
|
||||
|
|
@ -355,6 +356,7 @@
|
|||
D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFragment.swift; sourceTree = "<group>"; };
|
||||
D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModeFragment.swift; sourceTree = "<group>"; };
|
||||
D7E2E69E2CE356C90080DA0D /* PopupViewWithTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupViewWithTextField.swift; sourceTree = "<group>"; };
|
||||
D7E2E6A02CE5F87D0080DA0D /* QuickLookPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookPreview.swift; sourceTree = "<group>"; };
|
||||
D7E6ADF22B9875C20009A2BC /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
|
||||
D7E6ADF42B9876ED0009A2BC /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
||||
D7E6D0482AE933AD00A57AAF /* FavoriteContactsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteContactsListFragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -517,6 +519,7 @@
|
|||
C67586AF2C09F247002E77BF /* URIHandler.swift */,
|
||||
C6A5A9462C10B64A0070FEA4 /* SingleSignOn */,
|
||||
D79F2D092C47F4BF0038FA07 /* TouchFeedback.swift */,
|
||||
D7E2E6A02CE5F87D0080DA0D /* QuickLookPreview.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1216,6 +1219,7 @@
|
|||
66F08C892C2AFEF700D9AE2F /* MeetingsListBottomSheet.swift in Sources */,
|
||||
D726E43F2B19E56F0083C415 /* StartCallViewModel.swift in Sources */,
|
||||
D70A26EE2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift in Sources */,
|
||||
D7E2E6A12CE5F8850080DA0D /* QuickLookPreview.swift in Sources */,
|
||||
D7D1698C2AE66FA500109A5C /* MagicSearchSingleton.swift in Sources */,
|
||||
D714DE602C1B3B34006C1F1D /* RegisterViewModel.swift in Sources */,
|
||||
D70C82A72C85F5910087F43F /* ConversationForwardMessageViewModel.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ struct ChatBubbleView: View {
|
|||
@State private var timer: Timer?
|
||||
@State private var ephemeralLifetime: String = ""
|
||||
|
||||
@State private var selectedAttachment: Bool = false
|
||||
@State private var selectedAttachmentIndex: Int = 0
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
if eventLogMessage.eventModel.eventLogType == .ConferenceChatMessage {
|
||||
|
|
@ -488,6 +491,9 @@ struct ChatBubbleView: View {
|
|||
}
|
||||
UIApplication.shared.endEditing()
|
||||
}
|
||||
.fullScreenCover(isPresented: $selectedAttachment) {
|
||||
QuickLookFullScreenView(conversationViewModel: conversationViewModel, currentIndex: $selectedAttachmentIndex)
|
||||
}
|
||||
}
|
||||
|
||||
func containsDuplicates(strings: [String]) -> Bool {
|
||||
|
|
@ -554,6 +560,10 @@ struct ChatBubbleView: View {
|
|||
}
|
||||
.layoutPriority(-1)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: eventLogMessage.message.attachments.first!)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
} else {
|
||||
AsyncImage(url: eventLogMessage.message.attachments.first!.thumbnail) { phase in
|
||||
switch phase {
|
||||
|
|
@ -583,17 +593,29 @@ struct ChatBubbleView: View {
|
|||
.layoutPriority(-1)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.id(UUID())
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: eventLogMessage.message.attachments.first!)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
}
|
||||
} else if eventLogMessage.message.attachments.first!.type == .gif {
|
||||
if #available(iOS 16.0, *) {
|
||||
GifImageView(eventLogMessage.message.attachments.first!.thumbnail)
|
||||
.layoutPriority(-1)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: eventLogMessage.message.attachments.first!)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
} else {
|
||||
GifImageView(eventLogMessage.message.attachments.first!.thumbnail)
|
||||
.id(UUID())
|
||||
.layoutPriority(-1)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: eventLogMessage.message.attachments.first!)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -636,13 +658,17 @@ struct ChatBubbleView: View {
|
|||
.frame(width: geometryProxy.size.width - 110, height: 100)
|
||||
.background(.white)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: eventLogMessage.message.attachments.first!)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
}
|
||||
} else if eventLogMessage.message.attachments.count > 1 {
|
||||
let isGroup = conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup
|
||||
LazyVGrid(columns: [
|
||||
GridItem(.adaptive(minimum: 120), spacing: 1)
|
||||
], spacing: 3) {
|
||||
ForEach(eventLogMessage.message.attachments) { attachment in
|
||||
ForEach(eventLogMessage.message.attachments, id: \.id) { attachment in
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.fill(Color(.white))
|
||||
|
|
@ -668,6 +694,10 @@ struct ChatBubbleView: View {
|
|||
ProgressView()
|
||||
}
|
||||
.layoutPriority(-1)
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: attachment)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
} else {
|
||||
AsyncImage(url: attachment.thumbnail) { image in
|
||||
ZStack {
|
||||
|
|
@ -689,6 +719,10 @@ struct ChatBubbleView: View {
|
|||
}
|
||||
.id(UUID())
|
||||
.layoutPriority(-1)
|
||||
.onTapGesture {
|
||||
selectedAttachmentIndex = conversationViewModel.getAttachmentIndex(attachment: attachment)
|
||||
selectedAttachment.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ class ConversationViewModel: ObservableObject {
|
|||
@Published var isPlaying = false
|
||||
@Published var progress: Double = 0.0
|
||||
|
||||
@Published var attachments: [Attachment] = []
|
||||
|
||||
struct SheetCategory: Identifiable {
|
||||
let id = UUID()
|
||||
let name: String
|
||||
|
|
@ -392,6 +394,8 @@ class ConversationViewModel: ObservableObject {
|
|||
|
||||
self.conversationInfoPopupText = displayedConversation?.subject ?? ""
|
||||
|
||||
self.attachments.removeAll()
|
||||
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
if self.displayedConversation != nil {
|
||||
let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: 0, end: 30)
|
||||
|
|
@ -454,6 +458,11 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
if typeTmp != .voiceRecording {
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.type == "video" {
|
||||
let path = URL(string: self.getNewFilePath(name: content.name ?? ""))
|
||||
|
|
@ -471,6 +480,9 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -679,6 +691,11 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
if typeTmp != .voiceRecording {
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.type == "video" {
|
||||
let path = URL(string: self.getNewFilePath(name: content.name ?? ""))
|
||||
|
|
@ -696,6 +713,9 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -902,6 +922,11 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
if typeTmp != .voiceRecording {
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.type == "video" {
|
||||
let path = URL(string: self.getNewFilePath(name: content.name ?? ""))
|
||||
|
|
@ -919,6 +944,9 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1203,6 +1231,11 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
if typeTmp != .voiceRecording {
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.type == "video" {
|
||||
let path = URL(string: self.getNewFilePath(name: content.name ?? ""))
|
||||
|
|
@ -1220,6 +1253,9 @@ class ConversationViewModel: ObservableObject {
|
|||
)
|
||||
attachmentNameList += ", \(content.name!)"
|
||||
attachmentList.append(attachment)
|
||||
DispatchQueue.main.async {
|
||||
self.attachments.append(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2220,6 +2256,10 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getAttachmentIndex(attachment: Attachment) -> Int {
|
||||
return self.attachments.firstIndex(where: {$0.id == attachment.id}) ?? 0
|
||||
}
|
||||
}
|
||||
// swiftlint:enable line_length
|
||||
// swiftlint:enable type_body_length
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
import QuickLook
|
||||
|
||||
struct QuickLookFullScreenView: View {
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
@ObservedObject var conversationViewModel: ConversationViewModel
|
||||
|
||||
@Binding var currentIndex: Int
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
QuickLookPreview(fileURLs: conversationViewModel.attachments.map { $0.full }, startIndex: currentIndex)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .principal) {
|
||||
Text(conversationViewModel.attachments.first?.name ?? "File error")
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.font(.headline)
|
||||
}
|
||||
}
|
||||
.navigationBarItems(trailing: Button("Close") {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QuickLookPreview: UIViewControllerRepresentable {
|
||||
let fileURLs: [URL]
|
||||
let startIndex: Int
|
||||
|
||||
func makeUIViewController(context: Context) -> QLPreviewController {
|
||||
let previewController = QLPreviewController()
|
||||
previewController.dataSource = context.coordinator
|
||||
previewController.currentPreviewItemIndex = startIndex // Définir l’index de départ
|
||||
return previewController
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: QLPreviewController, context: Context) {
|
||||
// No update needed
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(self)
|
||||
}
|
||||
|
||||
class Coordinator: NSObject, QLPreviewControllerDataSource {
|
||||
var parent: QuickLookPreview
|
||||
|
||||
init(_ parent: QuickLookPreview) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
|
||||
return parent.fileURLs.count
|
||||
}
|
||||
|
||||
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||
return parent.fileURLs[index] as QLPreviewItem
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue