Add file player

This commit is contained in:
Benoit Martins 2024-11-14 17:46:25 +01:00
parent f548037fa2
commit 9a78e75722
4 changed files with 162 additions and 1 deletions

View file

@ -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 */,

View file

@ -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))

View file

@ -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

View file

@ -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 lindex 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
}
}
}