From bff25fc3f228a7ffc9fb5bda71335ea253a7dfea Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 12 Nov 2024 15:08:39 +0100 Subject: [PATCH] Allow admins to update conversation subject --- Linphone.xcodeproj/project.pbxproj | 24 +++-- Linphone/Localizable.xcstrings | 17 ++++ Linphone/UI/Main/ContentView.swift | 33 +++++++ .../Fragments/ConversationInfoFragment.swift | 1 + .../ViewModel/ConversationViewModel.swift | 23 +++++ .../Fragments/PopupViewWithTextField.swift | 87 +++++++++++++++++++ 6 files changed, 171 insertions(+), 14 deletions(-) create mode 100644 Linphone/UI/Main/Fragments/PopupViewWithTextField.swift diff --git a/Linphone.xcodeproj/project.pbxproj b/Linphone.xcodeproj/project.pbxproj index d837e61ab..0bf43c8c5 100644 --- a/Linphone.xcodeproj/project.pbxproj +++ b/Linphone.xcodeproj/project.pbxproj @@ -162,6 +162,7 @@ D7D24D182AC1B4E800C6F35B /* NotoSans-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D7D24D122AC1B4E800C6F35B /* NotoSans-ExtraBold.ttf */; }; 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 */; }; 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 */; }; @@ -353,6 +354,7 @@ D7D24D122AC1B4E800C6F35B /* NotoSans-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSans-ExtraBold.ttf"; sourceTree = ""; }; D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFragment.swift; sourceTree = ""; }; D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModeFragment.swift; sourceTree = ""; }; + D7E2E69E2CE356C90080DA0D /* PopupViewWithTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupViewWithTextField.swift; sourceTree = ""; }; D7E6ADF22B9875C20009A2BC /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; D7E6ADF42B9876ED0009A2BC /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = ""; }; D7E6D0482AE933AD00A57AAF /* FavoriteContactsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteContactsListFragment.swift; sourceTree = ""; }; @@ -687,6 +689,7 @@ C6DC4E3E2C19C289009096FD /* SideMenuEntry.swift */, C62817272C1B389700DBA646 /* SideMenuAccountRow.swift */, D7E6D04C2AEBD77600A57AAF /* CustomBottomSheet.swift */, + D7E2E69E2CE356C90080DA0D /* PopupViewWithTextField.swift */, ); path = Fragments; sourceTree = ""; @@ -1136,6 +1139,7 @@ C62817282C1B389700DBA646 /* SideMenuAccountRow.swift in Sources */, C60E8F192C0F649200A06DB8 /* UIApplicationExtension.swift in Sources */, D78290BB2ADD40B2004AA85C /* ContactViewModel.swift in Sources */, + D7E2E69F2CE356C90080DA0D /* PopupViewWithTextField.swift in Sources */, C67586B52C09F617002E77BF /* SingleSignOnManager.swift in Sources */, D7F4D9CB2B5FD27200CDCD76 /* CallsListFragment.swift in Sources */, C6A5A9482C10B6A30070FEA4 /* AuthState.swift in Sources */, @@ -1265,7 +1269,6 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "DEBUG=1", - "USE_CRASHLYTICS=1", ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = msgNotificationService/Info.plist; @@ -1279,7 +1282,7 @@ ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 6.0.0; - OTHER_SWIFT_FLAGS = "$(inherited) -DUSE_CRASHLYTICS"; + OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.msgNotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1305,10 +1308,7 @@ DEVELOPMENT_TEAM = Z2V957B3D6; ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "USE_CRASHLYTICS=1", - ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = msgNotificationService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = msgNotificationService; @@ -1321,7 +1321,7 @@ ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 6.0.0; - OTHER_SWIFT_FLAGS = "$(inherited) -DUSE_CRASHLYTICS"; + OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.msgNotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1468,7 +1468,6 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "DEBUG=1", - "USE_CRASHLYTICS=1", ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Linphone/Info.plist; @@ -1495,7 +1494,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 13.3; MARKETING_VERSION = 6.0.0; - OTHER_SWIFT_FLAGS = "$(inherited) -DUSE_CRASHLYTICS"; + OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -1521,10 +1520,7 @@ DEVELOPMENT_TEAM = Z2V957B3D6; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "USE_CRASHLYTICS=1", - ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Linphone/Info.plist; INFOPLIST_KEY_NSCameraUsageDescription = "Camera usage is required for video VOIP calls"; @@ -1550,7 +1546,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 13.3; MARKETING_VERSION = 6.0.0; - OTHER_SWIFT_FLAGS = "$(inherited) -DUSE_CRASHLYTICS"; + OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index 4267eeb33..a7ee0c03c 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -1064,6 +1064,23 @@ } } }, + "conversation_dialog_edit_subject" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Edit conversation subject" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renommer la conversation" + } + } + } + }, "conversation_dialog_set_subject" : { "extractionState" : "manual", "localizations" : { diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index e460256e7..dd5b34494 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -1189,6 +1189,39 @@ struct ContentView: View { } } + if isShowStartCallGroupPopup { + PopupView( + isShowPopup: $isShowStartCallGroupPopup, + title: Text("conversation_info_confirm_start_group_call_dialog_title"), + content: Text("conversation_info_confirm_start_group_call_dialog_message"), + titleFirstButton: Text("Cancel"), + actionFirstButton: { + self.isShowStartCallGroupPopup.toggle() + }, + titleSecondButton: Text("Confirm"), + actionSecondButton: { + if conversationViewModel.displayedConversation != nil { + conversationViewModel.displayedConversation!.createGroupCall() + } + self.isShowStartCallGroupPopup.toggle() + } + ) + .background(.black.opacity(0.65)) + .zIndex(3) + .onTapGesture { + self.isShowStartCallGroupPopup.toggle() + } + } + + if conversationViewModel.isShowConversationInfoPopup { + PopupViewWithTextField(conversationViewModel: conversationViewModel) + .background(.black.opacity(0.65)) + .zIndex(3) + .onTapGesture { + conversationViewModel.isShowConversationInfoPopup = false + } + } + if telecomManager.meetingWaitingRoomDisplayed { MeetingWaitingRoomFragment(meetingWaitingRoomViewModel: meetingWaitingRoomViewModel) .zIndex(3) diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationInfoFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationInfoFragment.swift index 8975ade93..ba5a3a4c9 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationInfoFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationInfoFragment.swift @@ -132,6 +132,7 @@ struct ConversationInfoFragment: View { if conversationViewModel.isUserAdmin { Button( action: { + conversationViewModel.isShowConversationInfoPopup = true }, label: { Image("pencil-simple") diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift index 6759c6331..ed9c1bea9 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift @@ -41,6 +41,9 @@ class ConversationViewModel: ObservableObject { @Published var isEphemeral: Bool = false @Published var ephemeralTime: String = NSLocalizedString("conversation_ephemeral_messages_duration_disabled", comment: "") + @Published var isShowConversationInfoPopup: Bool = false + @Published var conversationInfoPopupText: String = "" + // Used to keep track of a ChatRoom callback without having to worry about life cycle // Init will add the delegate, deinit will remove it class ChatRoomDelegateHolder { @@ -378,6 +381,8 @@ class ConversationViewModel: ObservableObject { self.mediasToSend.removeAll() self.messageToReply = nil + self.conversationInfoPopupText = displayedConversation?.subject ?? "" + coreContext.doOnCoreQueue { _ in if self.displayedConversation != nil { let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: 0, end: 30) @@ -2071,6 +2076,24 @@ class ConversationViewModel: ObservableObject { } } + func setNewChatRoomSubject() { + if self.displayedConversation != nil && self.conversationInfoPopupText != self.displayedConversation!.subject { + + coreContext.doOnCoreQueue { _ in + self.displayedConversation!.chatRoom.subject = self.conversationInfoPopupText + } + + self.displayedConversation!.subject = self.conversationInfoPopupText + self.displayedConversation!.avatarModel = ContactAvatarModel( + friend: self.displayedConversation!.avatarModel.friend, + name: self.conversationInfoPopupText, + address: self.displayedConversation!.avatarModel.address, + withPresence: false + ) + self.isShowConversationInfoPopup = false + } + } + func getEphemeralTime() { coreContext.doOnCoreQueue { _ in if self.displayedConversation != nil { diff --git a/Linphone/UI/Main/Fragments/PopupViewWithTextField.swift b/Linphone/UI/Main/Fragments/PopupViewWithTextField.swift new file mode 100644 index 000000000..c2495bec0 --- /dev/null +++ b/Linphone/UI/Main/Fragments/PopupViewWithTextField.swift @@ -0,0 +1,87 @@ +// +// PopupViewWithTextField.swift +// Linphone +// +// Created by BenoƮt Martins on 12/11/2024. +// + +import SwiftUI + +struct PopupViewWithTextField: View { + + @ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared + + @ObservedObject var conversationViewModel: ConversationViewModel + + @FocusState var isMessageTextFocused: Bool + + var body: some View { + GeometryReader { geometry in + VStack(alignment: .leading) { + Text("conversation_dialog_edit_subject") + .default_text_style_800(styleSize: 16) + .frame(alignment: .leading) + .padding(.bottom, 2) + + TextField("conversation_dialog_subject_hint", text: $conversationViewModel.conversationInfoPopupText) + .default_text_style(styleSize: 15) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isMessageTextFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isMessageTextFocused) + + Button(action: { + conversationViewModel.isShowConversationInfoPopup = false + }, label: { + Text("Cancel") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orangeMain500, lineWidth: 1) + ) + .padding(.bottom, 10) + + Button(action: { + conversationViewModel.setNewChatRoomSubject() + }, label: { + Text("Confirm") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(conversationViewModel.conversationInfoPopupText.isEmpty ? Color.orangeMain100 : Color.orangeMain500) + .cornerRadius(60) + .disabled(conversationViewModel.conversationInfoPopupText.isEmpty) + } + .padding(.horizontal, 20) + .padding(.vertical, 20) + .background(.white) + .cornerRadius(20) + .padding(.horizontal) + .frame(maxHeight: .infinity) + .shadow(color: Color.orangeMain500, radius: 0, x: 0, y: 2) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .position(x: geometry.size.width / 2, y: geometry.size.height / 2) + } + } +} + +#Preview { + PopupViewWithTextField(conversationViewModel: ConversationViewModel()) +}