From 233ff399ff2341cdf1493c434be1504890f5cab8 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 24 Sep 2024 18:20:56 +0200 Subject: [PATCH] Add event message --- .../clock-countdown.svg | 2 +- .../door.imageset/Contents.json | 21 + .../Assets.xcassets/door.imageset/door.svg | 1 + .../pencil-simple.imageset/pencil-simple.svg | 2 +- .../user-circle-gear.svg | 2 +- .../user-circle.imageset/user-circle.svg | 2 +- .../warning-circle.svg | 2 +- Linphone/Localizable.xcstrings | 204 ++++++++ .../Fragments/ChatBubbleView.swift | 452 ++++++++++-------- .../Fragments/ConversationFragment.swift | 10 + .../Main/Conversations/Fragments/UIList.swift | 2 +- .../Main/Conversations/Model/EventModel.swift | 122 +++++ .../ConversationForwardMessageViewModel.swift | 2 +- .../ViewModel/ConversationViewModel.swift | 64 +-- 14 files changed, 641 insertions(+), 247 deletions(-) create mode 100644 Linphone/Assets.xcassets/door.imageset/Contents.json create mode 100644 Linphone/Assets.xcassets/door.imageset/door.svg create mode 100644 Linphone/UI/Main/Conversations/Model/EventModel.swift diff --git a/Linphone/Assets.xcassets/clock-countdown.imageset/clock-countdown.svg b/Linphone/Assets.xcassets/clock-countdown.imageset/clock-countdown.svg index 548aeabcd..c59988986 100644 --- a/Linphone/Assets.xcassets/clock-countdown.imageset/clock-countdown.svg +++ b/Linphone/Assets.xcassets/clock-countdown.imageset/clock-countdown.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/door.imageset/Contents.json b/Linphone/Assets.xcassets/door.imageset/Contents.json new file mode 100644 index 000000000..d54a1df16 --- /dev/null +++ b/Linphone/Assets.xcassets/door.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "door.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/door.imageset/door.svg b/Linphone/Assets.xcassets/door.imageset/door.svg new file mode 100644 index 000000000..8952e8d49 --- /dev/null +++ b/Linphone/Assets.xcassets/door.imageset/door.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/pencil-simple.imageset/pencil-simple.svg b/Linphone/Assets.xcassets/pencil-simple.imageset/pencil-simple.svg index 35cfc71c7..ceb292bbf 100644 --- a/Linphone/Assets.xcassets/pencil-simple.imageset/pencil-simple.svg +++ b/Linphone/Assets.xcassets/pencil-simple.imageset/pencil-simple.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/user-circle-gear.imageset/user-circle-gear.svg b/Linphone/Assets.xcassets/user-circle-gear.imageset/user-circle-gear.svg index c406aac63..5b383bc57 100644 --- a/Linphone/Assets.xcassets/user-circle-gear.imageset/user-circle-gear.svg +++ b/Linphone/Assets.xcassets/user-circle-gear.imageset/user-circle-gear.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/user-circle.imageset/user-circle.svg b/Linphone/Assets.xcassets/user-circle.imageset/user-circle.svg index 761ce7d97..797854dd3 100644 --- a/Linphone/Assets.xcassets/user-circle.imageset/user-circle.svg +++ b/Linphone/Assets.xcassets/user-circle.imageset/user-circle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/warning-circle.imageset/warning-circle.svg b/Linphone/Assets.xcassets/warning-circle.imageset/warning-circle.svg index a04e6ff79..1b69e522a 100644 --- a/Linphone/Assets.xcassets/warning-circle.imageset/warning-circle.svg +++ b/Linphone/Assets.xcassets/warning-circle.imageset/warning-circle.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index 6fdd2ee8b..797be6b75 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -947,6 +947,210 @@ } } }, + "conversation_event_admin_set" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ is admin" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ est maintenant administrateur" + } + } + } + }, + "conversation_event_admin_unset" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ is no longer admin" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ n'est plus administrateur" + } + } + } + }, + "conversation_event_conference_created" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You have joined the group" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vous avez rejoint le groupe" + } + } + } + }, + "conversation_event_conference_destroyed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You have left the group" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vous avez quitté le groupe" + } + } + } + }, + "conversation_event_device_added" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "New device for %@" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouvel appareil pour %@" + } + } + } + }, + "conversation_event_device_removed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Device for %@ removed" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appareil supprimé pour %@" + } + } + } + }, + "conversation_event_ephemeral_messages_disabled" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ephemeral messages have been disabled" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les messages éphémères ont été désactivés" + } + } + } + }, + "conversation_event_ephemeral_messages_enabled" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ephemeral messages have been enabled" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Les messages éphémères ont été activés" + } + } + } + }, + "conversation_event_ephemeral_messages_lifetime_changed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ephemeral lifetime is now %@" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "La durée des messages éphémères est de %@" + } + } + } + }, + "conversation_event_participant_added" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ has joined" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ a rejoint le groupe" + } + } + } + }, + "conversation_event_participant_removed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ has left" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ a quitté le groupe" + } + } + } + }, + "conversation_event_subject_changed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "New subject: %@" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Le groupe a été renommé : %@" + } + } + } + }, "conversation_failed_to_create_toast" : { "extractionState" : "manual", "localizations" : { diff --git a/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift b/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift index fd37145de..4ad63f305 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ChatBubbleView.swift @@ -36,244 +36,272 @@ struct ChatBubbleView: View { var body: some View { HStack { - VStack { - if !eventLogMessage.message.text.isEmpty || !eventLogMessage.message.attachments.isEmpty { - HStack(alignment: .top, content: { - if eventLogMessage.message.isOutgoing { - Spacer() - } - if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup - && !eventLogMessage.message.isOutgoing && eventLogMessage.message.isFirstMessage { - VStack { - Avatar( - contactAvatarModel: conversationViewModel.participantConversationModel.first(where: {$0.address == eventLogMessage.message.address}) ?? - ContactAvatarModel(friend: nil, name: "??", address: "", withPresence: false), - avatarSize: 35 - ) - .padding(.top, 30) + if eventLogMessage.eventModel.eventLogType == .ConferenceChatMessage { + VStack { + if !eventLogMessage.message.text.isEmpty || !eventLogMessage.message.attachments.isEmpty { + HStack(alignment: .top, content: { + if eventLogMessage.message.isOutgoing { + Spacer() } - } else if conversationViewModel.displayedConversation != nil - && conversationViewModel.displayedConversation!.isGroup && !eventLogMessage.message.isOutgoing { - VStack { - } - .padding(.leading, 43) - } - - VStack(alignment: .leading, spacing: 0) { - if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup + if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup && !eventLogMessage.message.isOutgoing && eventLogMessage.message.isFirstMessage { - Text(conversationViewModel.participantConversationModel.first(where: {$0.address == eventLogMessage.message.address})?.name ?? "") - .default_text_style(styleSize: 12) - .padding(.top, 10) - .padding(.bottom, 2) - } - - if eventLogMessage.message.isForward { - HStack { - if eventLogMessage.message.isOutgoing { - Spacer() - } - - VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading, spacing: 0) { - HStack { - Image("forward") - .resizable() - .frame(width: 15, height: 15, alignment: .leading) - - Text("message_forwarded_label") - .default_text_style(styleSize: 12) - } - .padding(.bottom, 2) - } - - if !eventLogMessage.message.isOutgoing { - Spacer() - } + VStack { + Avatar( + contactAvatarModel: conversationViewModel.participantConversationModel.first(where: {$0.address == eventLogMessage.message.address}) ?? + ContactAvatarModel(friend: nil, name: "??", address: "", withPresence: false), + avatarSize: 35 + ) + .padding(.top, 30) } - .frame(maxWidth: .infinity) + } else if conversationViewModel.displayedConversation != nil + && conversationViewModel.displayedConversation!.isGroup && !eventLogMessage.message.isOutgoing { + VStack { + } + .padding(.leading, 43) } - if eventLogMessage.message.replyMessage != nil { - HStack { - if eventLogMessage.message.isOutgoing { - Spacer() - } - - VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading, spacing: 0) { - HStack { - Image("reply") - .resizable() - .frame(width: 15, height: 15, alignment: .leading) - - Text(conversationViewModel.participantConversationModel.first( - where: {$0.address == eventLogMessage.message.replyMessage!.address})?.name ?? "") - .default_text_style(styleSize: 12) - } + VStack(alignment: .leading, spacing: 0) { + if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup + && !eventLogMessage.message.isOutgoing && eventLogMessage.message.isFirstMessage { + Text(conversationViewModel.participantConversationModel.first(where: {$0.address == eventLogMessage.message.address})?.name ?? "") + .default_text_style(styleSize: 12) + .padding(.top, 10) .padding(.bottom, 2) + } + + if eventLogMessage.message.isForward { + HStack { + if eventLogMessage.message.isOutgoing { + Spacer() + } - VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) { - if !eventLogMessage.message.replyMessage!.text.isEmpty { - Text(eventLogMessage.message.replyMessage!.text) - .foregroundStyle(Color.grayMain2c700) - .default_text_style(styleSize: 16) - .lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/) - } else if !eventLogMessage.message.replyMessage!.attachmentsNames.isEmpty { - Text(eventLogMessage.message.replyMessage!.attachmentsNames) - .foregroundStyle(Color.grayMain2c700) - .default_text_style(styleSize: 16) - .lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/) - } - } - .padding(.all, 15) - .padding(.bottom, 15) - .background(Color.gray200) - .clipShape(RoundedRectangle(cornerRadius: 1)) - .roundedCorner( - 16, - corners: eventLogMessage.message.isOutgoing ? [.topLeft, .topRight, .bottomLeft] : [.topLeft, .topRight, .bottomRight] - ) - } - .onTapGesture { - conversationViewModel.scrollToMessage(message: eventLogMessage.message) - } - - if !eventLogMessage.message.isOutgoing { - Spacer() - } - } - .frame(maxWidth: .infinity) - .padding(.bottom, -20) - } - - ZStack { - HStack { - if eventLogMessage.message.isOutgoing { - Spacer() - } - - VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) { - VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) { - if !eventLogMessage.message.attachments.isEmpty { - messageAttachments() - } - - if !eventLogMessage.message.text.isEmpty { - Text(eventLogMessage.message.text) - .foregroundStyle(Color.grayMain2c700) - .default_text_style(styleSize: 16) - } - - HStack(alignment: .center) { - Text(conversationViewModel.getMessageTime(startDate: eventLogMessage.message.dateReceived)) - .foregroundStyle(Color.grayMain2c500) - .default_text_style_300(styleSize: 14) - .padding(.top, 1) + VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading, spacing: 0) { + HStack { + Image("forward") + .resizable() + .frame(width: 15, height: 15, alignment: .leading) - if (conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup) - || eventLogMessage.message.isOutgoing { - if eventLogMessage.message.status == .sending { - ProgressView() - .controlSize(.mini) - .progressViewStyle(CircularProgressViewStyle(tint: .orangeMain500)) - .frame(width: 10, height: 10) - .padding(.top, 1) - } else if eventLogMessage.message.status != nil { - Image(conversationViewModel.getImageIMDN(status: eventLogMessage.message.status!)) - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orangeMain500) - .frame(width: 15, height: 15) - .padding(.top, 1) - } + Text("message_forwarded_label") + .default_text_style(styleSize: 12) + } + .padding(.bottom, 2) + } + + if !eventLogMessage.message.isOutgoing { + Spacer() + } + } + .frame(maxWidth: .infinity) + } + + if eventLogMessage.message.replyMessage != nil { + HStack { + if eventLogMessage.message.isOutgoing { + Spacer() + } + + VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading, spacing: 0) { + HStack { + Image("reply") + .resizable() + .frame(width: 15, height: 15, alignment: .leading) + + Text(conversationViewModel.participantConversationModel.first( + where: {$0.address == eventLogMessage.message.replyMessage!.address})?.name ?? "") + .default_text_style(styleSize: 12) + } + .padding(.bottom, 2) + + VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) { + if !eventLogMessage.message.replyMessage!.text.isEmpty { + Text(eventLogMessage.message.replyMessage!.text) + .foregroundStyle(Color.grayMain2c700) + .default_text_style(styleSize: 16) + .lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/) + } else if !eventLogMessage.message.replyMessage!.attachmentsNames.isEmpty { + Text(eventLogMessage.message.replyMessage!.attachmentsNames) + .foregroundStyle(Color.grayMain2c700) + .default_text_style(styleSize: 16) + .lineLimit(/*@START_MENU_TOKEN@*/2/*@END_MENU_TOKEN@*/) } } - .onTapGesture { - conversationViewModel.selectedMessageToDisplayDetails = eventLogMessage - conversationViewModel.prepareBottomSheetForDeliveryStatus() - } - .disabled(conversationViewModel.selectedMessage != nil) - .padding(.top, -4) + .padding(.all, 15) + .padding(.bottom, 15) + .background(Color.gray200) + .clipShape(RoundedRectangle(cornerRadius: 1)) + .roundedCorner( + 16, + corners: eventLogMessage.message.isOutgoing ? [.topLeft, .topRight, .bottomLeft] : [.topLeft, .topRight, .bottomRight] + ) + } + .onTapGesture { + conversationViewModel.scrollToMessage(message: eventLogMessage.message) } - .padding(.all, 15) - .background(eventLogMessage.message.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100) - .clipShape(RoundedRectangle(cornerRadius: 3)) - .roundedCorner( - 16, - corners: eventLogMessage.message.isOutgoing && eventLogMessage.message.isFirstMessage ? [.topLeft, .topRight, .bottomLeft] : - (!eventLogMessage.message.isOutgoing && eventLogMessage.message.isFirstMessage ? [.topRight, .bottomRight, .bottomLeft] : [.allCorners])) - if !eventLogMessage.message.reactions.isEmpty { - HStack { - ForEach(0... + */ + +import SwiftUI +import linphonesw + +class EventModel: ObservableObject { + @Published var text: String + @Published var icon: Image? + + var eventLog: EventLog + var eventLogType: EventLog.Kind + + init(eventLog: EventLog) { + self.eventLog = eventLog + self.eventLogType = eventLog.type + self.text = "" + self.icon = nil + setupEventData() + } + + private func setupEventData() { + let address = eventLog.participantAddress ?? eventLog.peerAddress + if address != nil { + ContactsManager.shared.getFriendWithAddressInCoreQueue(address: address) { friendResult in + var name = "" + if let addressFriend = friendResult { + name = addressFriend.name! + } else { + name = address!.displayName != nil ? address!.displayName! : address!.username! + } + + let textValue: String + let iconValue: Image? + + switch self.eventLog.type { + case .ConferenceCreated: + textValue = NSLocalizedString("conversation_event_conference_created", comment: "") + case .ConferenceTerminated: + textValue = NSLocalizedString("conversation_event_conference_destroyed", comment: "") + case .ConferenceParticipantAdded: + textValue = String(format: NSLocalizedString("conversation_event_participant_added", comment: ""), address != nil ? name : "") + case .ConferenceParticipantRemoved: + textValue = String(format: NSLocalizedString("conversation_event_participant_removed", comment: ""), address != nil ? name : "") + case .ConferenceSubjectChanged: + textValue = String(format: NSLocalizedString("conversation_event_subject_changed", comment: ""), self.eventLog.subject ?? "") + case .ConferenceParticipantSetAdmin: + textValue = String(format: NSLocalizedString("conversation_event_admin_set", comment: ""), address != nil ? name : "") + case .ConferenceParticipantUnsetAdmin: + textValue = String(format: NSLocalizedString("conversation_event_admin_unset", comment: ""), address != nil ? name : "") + case .ConferenceParticipantDeviceAdded: + textValue = String(format: NSLocalizedString("conversation_event_device_added", comment: ""), address != nil ? name : "") + case .ConferenceParticipantDeviceRemoved: + textValue = String(format: NSLocalizedString("conversation_event_device_removed", comment: ""), address != nil ? name : "") + case .ConferenceEphemeralMessageEnabled: + textValue = NSLocalizedString("conversation_event_ephemeral_messages_enabled", comment: "") + case .ConferenceEphemeralMessageDisabled: + textValue = NSLocalizedString("conversation_event_ephemeral_messages_disabled", comment: "") + case .ConferenceEphemeralMessageLifetimeChanged: + textValue = String(format: NSLocalizedString("conversation_event_ephemeral_messages_lifetime_changed", comment: ""), + self.formatEphemeralExpiration(duration: Int64(self.eventLog.ephemeralMessageLifetime)).lowercased()) + default: + textValue = String(self.eventLog.type.rawValue) + } + + // Icon assignment + switch self.eventLog.type { + case .ConferenceEphemeralMessageEnabled, .ConferenceEphemeralMessageDisabled, .ConferenceEphemeralMessageLifetimeChanged: + iconValue = Image("clock-countdown") + case .ConferenceTerminated: + iconValue = Image("warning-circle") + case .ConferenceSubjectChanged: + iconValue = Image("pencil-simple") + case .ConferenceParticipantAdded, .ConferenceParticipantRemoved, .ConferenceParticipantDeviceAdded, .ConferenceParticipantDeviceRemoved: + iconValue = Image("door") + default: + iconValue = Image("user-circle") + } + + DispatchQueue.main.async { + self.text = textValue + self.icon = iconValue + } + } + } + } + + private func formatEphemeralExpiration(duration: Int64) -> String { + switch duration { + case 0: + return NSLocalizedString("conversation_ephemeral_messages_duration_disabled", comment: "") + case 60: + return NSLocalizedString("conversation_ephemeral_messages_duration_one_minute", comment: "") + case 3600: + return NSLocalizedString("conversation_ephemeral_messages_duration_one_hour", comment: "") + case 86400: + return NSLocalizedString("conversation_ephemeral_messages_duration_one_day", comment: "") + case 259200: + return NSLocalizedString("conversation_ephemeral_messages_duration_three_days", comment: "") + case 604800: + return NSLocalizedString("conversation_ephemeral_messages_duration_one_week", comment: "") + default: + return "\(duration) s" + } + } +} diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationForwardMessageViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationForwardMessageViewModel.swift index 6217bc9c1..eaabb4f48 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationForwardMessageViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationForwardMessageViewModel.swift @@ -280,7 +280,7 @@ class ConversationForwardMessageViewModel: ObservableObject { func forwardMessage() { CoreContext.shared.doOnCoreQueue { _ in if self.displayedConversation != nil && self.selectedMessage != nil { - if let messageToForward = self.selectedMessage!.eventLog.chatMessage { + if let messageToForward = self.selectedMessage!.eventModel.eventLog.chatMessage { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { do { let forwardedMessage = try self.displayedConversation!.chatRoom.createForwardMessage(message: messageToForward) diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift index f4ea9e59a..c06f29420 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift @@ -125,7 +125,7 @@ class ConversationViewModel: ObservableObject { } if !self.conversationMessagesSection.isEmpty && !self.conversationMessagesSection[0].rows.isEmpty { - if let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventLog.chatMessage?.messageId == message.messageId}) { + if let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId}) { if indexMessage < self.conversationMessagesSection[0].rows.count && self.conversationMessagesSection[0].rows[indexMessage].message.status != statusTmp { DispatchQueue.main.async { self.objectWillChange.send() @@ -153,7 +153,7 @@ class ConversationViewModel: ObservableObject { statusTmp = .sending } - let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventLog.chatMessage?.messageId == message.messageId}) + let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId}) DispatchQueue.main.async { if indexMessage != nil { @@ -162,7 +162,7 @@ class ConversationViewModel: ObservableObject { } } }, onNewMessageReaction: { (message: ChatMessage, _: ChatMessageReaction) in - let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventLog.chatMessage?.messageId == message.messageId}) + let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId}) var reactionsTmp: [String] = [] message.reactions.forEach({ chatMessageReaction in reactionsTmp.append(chatMessageReaction.body) @@ -175,7 +175,7 @@ class ConversationViewModel: ObservableObject { } } }, onReactionRemoved: { (message: ChatMessage, _: Address) in - let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventLog.chatMessage?.messageId == message.messageId}) + let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId}) var reactionsTmp: [String] = [] message.reactions.forEach({ chatMessageReaction in reactionsTmp.append(chatMessageReaction.body) @@ -453,7 +453,7 @@ class ConversationViewModel: ObservableObject { if eventLog.chatMessage != nil { conversationMessage.append( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: !eventLog.chatMessage!.messageId.isEmpty ? eventLog.chatMessage!.messageId : UUID().uuidString, status: statusTmp, @@ -474,9 +474,9 @@ class ConversationViewModel: ObservableObject { self.addChatMessageDelegate(message: eventLog.chatMessage!) } else { - conversationMessage.insert( + conversationMessage.append( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: UUID().uuidString, status: nil, @@ -489,7 +489,7 @@ class ConversationViewModel: ObservableObject { ownReaction: "", reactions: [] ) - ), at: 0 + ) ) } } @@ -672,7 +672,7 @@ class ConversationViewModel: ObservableObject { if eventLog.chatMessage != nil { conversationMessagesTmp.insert( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: !eventLog.chatMessage!.messageId.isEmpty ? eventLog.chatMessage!.messageId : UUID().uuidString, status: statusTmp, @@ -695,7 +695,7 @@ class ConversationViewModel: ObservableObject { } else { conversationMessagesTmp.insert( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: UUID().uuidString, status: nil, @@ -902,7 +902,7 @@ class ConversationViewModel: ObservableObject { if eventLog.chatMessage != nil { let message = EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: !eventLog.chatMessage!.messageId.isEmpty ? eventLog.chatMessage!.messageId : UUID().uuidString, appData: eventLog.chatMessage!.appdata ?? "", @@ -943,7 +943,7 @@ class ConversationViewModel: ObservableObject { } } else { let message = EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: UUID().uuidString, status: nil, @@ -987,7 +987,7 @@ class ConversationViewModel: ObservableObject { func scrollToMessage(message: Message) { coreContext.doOnCoreQueue { _ in if message.replyMessage != nil { - if let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventLog.chatMessage?.messageId == message.replyMessage!.id}) { + if let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.replyMessage!.id}) { NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onScrollToIndex"), object: nil, userInfo: ["index": indexMessage, "animated": true]) } else { if self.conversationMessagesSection[0].rows.last != nil { @@ -1177,7 +1177,7 @@ class ConversationViewModel: ObservableObject { if eventLog.chatMessage != nil { conversationMessagesTmp.insert( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: !eventLog.chatMessage!.messageId.isEmpty ? eventLog.chatMessage!.messageId : UUID().uuidString, status: statusTmp, @@ -1200,7 +1200,7 @@ class ConversationViewModel: ObservableObject { } else { conversationMessagesTmp.insert( EventLogMessage( - eventLog: eventLog, + eventModel: EventModel(eventLog: eventLog), message: Message( id: UUID().uuidString, status: nil, @@ -1243,7 +1243,7 @@ class ConversationViewModel: ObservableObject { do { var message: ChatMessage? if self.messageToReply != nil { - let chatMessageToReply = self.messageToReply!.eventLog.chatMessage + let chatMessageToReply = self.messageToReply!.eventModel.eventLog.chatMessage if chatMessageToReply != nil { message = try self.displayedConversation!.chatRoom.createReplyMessage(message: chatMessageToReply!) } @@ -1482,7 +1482,7 @@ class ConversationViewModel: ObservableObject { coreContext.doOnCoreQueue { _ in if self.selectedMessageToDisplayDetails != nil { Log.info("[ConversationViewModel] Remove reaction to message with ID \(self.selectedMessageToDisplayDetails!.message.id)") - let messageToSendReaction = self.selectedMessageToDisplayDetails!.eventLog.chatMessage + let messageToSendReaction = self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage if messageToSendReaction != nil { do { let reaction = try messageToSendReaction!.createReaction(utf8Reaction: "") @@ -1509,7 +1509,7 @@ class ConversationViewModel: ObservableObject { coreContext.doOnCoreQueue { _ in if self.selectedMessage != nil { Log.info("[ConversationViewModel] Sending reaction \(emoji) to message with ID \(self.selectedMessage!.message.id)") - let messageToSendReaction = self.selectedMessage!.eventLog.chatMessage + let messageToSendReaction = self.selectedMessage!.eventModel.eventLog.chatMessage if messageToSendReaction != nil { do { let reaction = try messageToSendReaction!.createReaction(utf8Reaction: messageToSendReaction?.ownReaction?.body == emoji ? "" : emoji) @@ -1533,9 +1533,9 @@ class ConversationViewModel: ObservableObject { func resend() { coreContext.doOnCoreQueue { _ in - if self.selectedMessage != nil && self.selectedMessage!.eventLog.chatMessage != nil { - Log.info("[ConversationViewModel] Re-sending message with ID \(self.selectedMessage!.eventLog.chatMessage!)") - self.selectedMessage!.eventLog.chatMessage!.send() + if self.selectedMessage != nil && self.selectedMessage!.eventModel.eventLog.chatMessage != nil { + Log.info("[ConversationViewModel] Re-sending message with ID \(self.selectedMessage!.eventModel.eventLog.chatMessage!)") + self.selectedMessage!.eventModel.eventLog.chatMessage!.send() } } } @@ -1543,9 +1543,9 @@ class ConversationViewModel: ObservableObject { func prepareBottomSheetForDeliveryStatus() { self.sheetCategories.removeAll() coreContext.doOnCoreQueue { _ in - if self.selectedMessageToDisplayDetails != nil && self.selectedMessageToDisplayDetails!.eventLog.chatMessage != nil { + if self.selectedMessageToDisplayDetails != nil && self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage != nil { - let participantsImdnDisplayed = self.selectedMessageToDisplayDetails!.eventLog.chatMessage!.getParticipantsByImdnState(state: .Displayed) + let participantsImdnDisplayed = self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage!.getParticipantsByImdnState(state: .Displayed) var participantListDisplayed: [InnerSheetCategory] = [] participantsImdnDisplayed.forEach({ participantImdn in if participantImdn.participant != nil && participantImdn.participant!.address != nil { @@ -1556,7 +1556,7 @@ class ConversationViewModel: ObservableObject { } }) - let participantsImdnDeliveredToUser = self.selectedMessageToDisplayDetails!.eventLog.chatMessage!.getParticipantsByImdnState(state: .DeliveredToUser) + let participantsImdnDeliveredToUser = self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage!.getParticipantsByImdnState(state: .DeliveredToUser) var participantListDeliveredToUser: [InnerSheetCategory] = [] participantsImdnDeliveredToUser.forEach({ participantImdn in if participantImdn.participant != nil && participantImdn.participant!.address != nil { @@ -1567,7 +1567,7 @@ class ConversationViewModel: ObservableObject { } }) - let participantsImdnDelivered = self.selectedMessageToDisplayDetails!.eventLog.chatMessage!.getParticipantsByImdnState(state: .Delivered) + let participantsImdnDelivered = self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage!.getParticipantsByImdnState(state: .Delivered) var participantListDelivered: [InnerSheetCategory] = [] participantsImdnDelivered.forEach({ participantImdn in if participantImdn.participant != nil && participantImdn.participant!.address != nil { @@ -1578,7 +1578,7 @@ class ConversationViewModel: ObservableObject { } }) - let participantsImdnNotDelivered = self.selectedMessageToDisplayDetails!.eventLog.chatMessage!.getParticipantsByImdnState(state: .NotDelivered) + let participantsImdnNotDelivered = self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage!.getParticipantsByImdnState(state: .NotDelivered) var participantListNotDelivered: [InnerSheetCategory] = [] participantsImdnNotDelivered.forEach({ participantImdn in if participantImdn.participant != nil && participantImdn.participant!.address != nil { @@ -1604,7 +1604,7 @@ class ConversationViewModel: ObservableObject { func prepareBottomSheetForReactions() { self.sheetCategories.removeAll() coreContext.doOnCoreQueue { core in - if self.selectedMessageToDisplayDetails != nil && self.selectedMessageToDisplayDetails!.eventLog.chatMessage != nil { + if self.selectedMessageToDisplayDetails != nil && self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage != nil { let dispatchGroup = DispatchGroup() var sheetCategoriesTmp: [SheetCategory] = [] @@ -1612,7 +1612,7 @@ class ConversationViewModel: ObservableObject { var participantList: [[InnerSheetCategory]] = [[]] var reactionList: [String] = [] - self.selectedMessageToDisplayDetails!.eventLog.chatMessage!.reactions.forEach { chatMessageReaction in + self.selectedMessageToDisplayDetails!.eventModel.eventLog.chatMessage!.reactions.forEach { chatMessageReaction in if chatMessageReaction.fromAddress != nil { dispatchGroup.enter() ContactAvatarModel.getAvatarModelFromAddress(address: chatMessageReaction.fromAddress!) { avatarResult in @@ -1701,6 +1701,14 @@ class ConversationViewModel: ObservableObject { } } } + + func compose() { + coreContext.doOnCoreQueue { _ in + if self.displayedConversation != nil { + self.displayedConversation!.chatRoom.compose() + } + } + } } // swiftlint:enable line_length // swiftlint:enable type_body_length