diff --git a/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift b/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift index 5b9250c7b..557637086 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift @@ -194,9 +194,11 @@ struct ChatBubbleView: View { } placeholder: { ProgressView() } + .id(UUID()) .layoutPriority(-1) - } else { + } else if message.attachments.first!.type == .gif { GifImageView(message.attachments.first!.full) + .id(UUID()) .layoutPriority(-1) .clipShape(RoundedRectangle(cornerRadius: 4)) } @@ -204,6 +206,39 @@ struct ChatBubbleView: View { .clipShape(RoundedRectangle(cornerRadius: 4)) .clipped() } + } else if message.attachments.count > 1 { + let isGroup = conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup + LazyVGrid(columns: [ + GridItem(.adaptive(minimum: 120), spacing: 1) + ], spacing: 3) { + ForEach(message.attachments) { attachment in + if attachment.type == .image || attachment.type == .gif { + ZStack { + Rectangle() + .fill(Color(.white)) + .frame(width: 120, height: 120) + + AsyncImage(url: attachment.full) { image in + image + .resizable() + .interpolation(.medium) + .aspectRatio(contentMode: .fill) + } placeholder: { + ProgressView() + } + .id(UUID()) + .layoutPriority(-1) + } + .clipShape(RoundedRectangle(cornerRadius: 4)) + .clipped() + } + } + } + .frame( + width: geometryProxy.size.width > 0 && CGFloat(122 * message.attachments.count) > geometryProxy.size.width - 110 - (isGroup ? 40 : 0) + ? 122 * floor(CGFloat(geometryProxy.size.width - 110 - (isGroup ? 40 : 0)) / 122) + : CGFloat(122 * message.attachments.count) + ) } } diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift index 390276357..f34753f70 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift @@ -194,13 +194,22 @@ class ConversationViewModel: ObservableObject { var conversationMessagesTmp: [Message] = [] historyEvents.enumerated().reversed().forEach { index, eventLog in - let attachmentList: [Attachment] = [] + var attachmentList: [Attachment] = [] var contentText = "" if eventLog.chatMessage != nil && !eventLog.chatMessage!.contents.isEmpty { eventLog.chatMessage!.contents.forEach { content in if content.isText { contentText = content.utf8Text ?? "" + } else { + if content.filePath == nil || content.filePath!.isEmpty { + self.downloadContent(chatMessage: eventLog.chatMessage!, content: content) + } else { + if URL(string: self.getNewFilePath(name: content.name ?? "")) != nil { + let attachment = Attachment(id: UUID().uuidString, url: URL(string: self.getNewFilePath(name: content.name ?? ""))!, type: (content.name?.lowercased().hasSuffix("gif"))! ? .gif : .image) + attachmentList.append(attachment) + } + } } } } @@ -458,7 +467,7 @@ class ConversationViewModel: ObservableObject { let contentName = content.name if contentName != nil { let isImage = FileUtil.isExtensionImage(path: contentName!) - let file = FileUtil.getFileStoragePath(fileName: contentName!, isImage: isImage) + let file = FileUtil.getFileStoragePath(fileName: contentName!.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? "", isImage: isImage) content.filePath = file Log.info( "[ConversationViewModel] File \(contentName) will be downloaded at \(content.filePath)" @@ -471,7 +480,7 @@ class ConversationViewModel: ObservableObject { } func getNewFilePath(name: String) -> String { - return "file://" + Factory.Instance.getDownloadDir(context: nil) + name + return "file://" + Factory.Instance.getDownloadDir(context: nil) + (name.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? "") } func getMessageTime(startDate: time_t) -> String {