From 7bae9fd3429e7ac403ed840b12910467b29be164 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 9 Jul 2024 14:05:40 +0200 Subject: [PATCH] Add participants during a conference call --- Linphone/UI/Call/CallView.swift | 7 +- .../Fragments/ParticipantsListFragment.swift | 159 +++++++++--------- .../UI/Call/ViewModel/CallViewModel.swift | 25 ++- 3 files changed, 114 insertions(+), 77 deletions(-) diff --git a/Linphone/UI/Call/CallView.swift b/Linphone/UI/Call/CallView.swift index 25601cccb..784bfa2a4 100644 --- a/Linphone/UI/Call/CallView.swift +++ b/Linphone/UI/Call/CallView.swift @@ -34,6 +34,8 @@ struct CallView: View { @ObservedObject var callViewModel: CallViewModel + @State private var addParticipantsViewModel: AddParticipantsViewModel? + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } @State private var orientation = UIDevice.current.orientation @@ -177,9 +179,12 @@ struct CallView: View { } if isShowParticipantsListFragment { - ParticipantsListFragment(callViewModel: callViewModel, isShowParticipantsListFragment: $isShowParticipantsListFragment) + ParticipantsListFragment(callViewModel: callViewModel, addParticipantsViewModel: addParticipantsViewModel ?? AddParticipantsViewModel(), isShowParticipantsListFragment: $isShowParticipantsListFragment) .zIndex(4) .transition(.move(edge: .bottom)) + .onAppear { + addParticipantsViewModel = AddParticipantsViewModel() + } } if callViewModel.zrtpPopupDisplayed == true { diff --git a/Linphone/UI/Call/Fragments/ParticipantsListFragment.swift b/Linphone/UI/Call/Fragments/ParticipantsListFragment.swift index 31152edb7..41c77a110 100644 --- a/Linphone/UI/Call/Fragments/ParticipantsListFragment.swift +++ b/Linphone/UI/Call/Fragments/ParticipantsListFragment.swift @@ -28,6 +28,8 @@ struct ParticipantsListFragment: View { @ObservedObject var callViewModel: CallViewModel + @ObservedObject var addParticipantsViewModel: AddParticipantsViewModel + @State private var delayedColor = Color.white @Binding var isShowParticipantsListFragment: Bool @@ -36,89 +38,96 @@ struct ParticipantsListFragment: View { @State private var indexToRemove = -1 var body: some View { - ZStack { - VStack(spacing: 1) { - Rectangle() - .foregroundColor(delayedColor) - .edgesIgnoringSafeArea(.top) - .frame(height: 0) - .task(delayColor) - - HStack { - Image("caret-left") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orangeMain500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, 2) - .padding(.leading, -10) - .onTapGesture { - delayColorDismiss() - withAnimation { - isShowParticipantsListFragment.toggle() + NavigationView { + ZStack { + VStack(spacing: 1) { + Rectangle() + .foregroundColor(delayedColor) + .edgesIgnoringSafeArea(.top) + .frame(height: 0) + .task(delayColor) + + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.orangeMain500) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + .padding(.top, 2) + .padding(.leading, -10) + .onTapGesture { + delayColorDismiss() + withAnimation { + isShowParticipantsListFragment.toggle() + } } + + Text("\(callViewModel.participantList.count + 1) \(callViewModel.participantList.isEmpty ? "Participant" : "Participants")") + .multilineTextAlignment(.leading) + .default_text_style_orange_800(styleSize: 16) + + Spacer() + + } + .frame(maxWidth: .infinity) + .frame(height: 50) + .padding(.horizontal) + .padding(.bottom, 4) + .background(.white) + + participantsList + + HStack { + Spacer() + + if callViewModel.myParticipantModel!.isAdmin { + NavigationLink(destination: { + AddParticipantsFragment(addParticipantsViewModel: addParticipantsViewModel, confirmAddParticipantsFunc: callViewModel.addParticipants) + .onAppear { + addParticipantsViewModel.participantsToAdd = [] + } + }, label: { + Image("plus") + .resizable() + .renderingMode(.template) + .frame(width: 25, height: 25) + .foregroundStyle(.white) + .padding() + .background(Color.orangeMain500) + .clipShape(Circle()) + .shadow(color: .black.opacity(0.2), radius: 4) + + }) + .padding() } - - Text("\(callViewModel.participantList.count + 1) \(callViewModel.participantList.isEmpty ? "Participant" : "Participants")") - .multilineTextAlignment(.leading) - .default_text_style_orange_800(styleSize: 16) - - Spacer() - + } + .padding(.trailing, 10) } - .frame(maxWidth: .infinity) - .frame(height: 50) - .padding(.horizontal) - .padding(.bottom, 4) .background(.white) - participantsList - - HStack { - Spacer() - - NavigationLink(destination: { - //AddParticipantsFragment() - }, label: { - Image("plus") - .resizable() - .renderingMode(.template) - .frame(width: 25, height: 25) - .foregroundStyle(.white) - .padding() - .background(Color.orangeMain500) - .clipShape(Circle()) - .shadow(color: .black.opacity(0.2), radius: 4) - + if self.isShowPopup { + let contentPopup = Text("Etes-vous sûr de vouloir supprimer \(callViewModel.participantList[indexToRemove].name) ?") + PopupView(isShowPopup: $isShowPopup, + title: Text("Supprimer un participant"), + content: contentPopup, + titleFirstButton: Text("Non"), + actionFirstButton: {self.isShowPopup.toggle()}, + titleSecondButton: Text("Oui"), + actionSecondButton: { + callViewModel.removeParticipant(index: indexToRemove) + self.isShowPopup.toggle() + indexToRemove = -1 }) - .padding() - } - .padding(.trailing, 10) - } - .background(.white) - - if self.isShowPopup { - let contentPopup = Text("Etes-vous sûr de vouloir supprimer \(callViewModel.participantList[indexToRemove].name) ?") - PopupView(isShowPopup: $isShowPopup, - title: Text("Supprimer un participant"), - content: contentPopup, - titleFirstButton: Text("Non"), - actionFirstButton: {self.isShowPopup.toggle()}, - titleSecondButton: Text("Oui"), - actionSecondButton: { - callViewModel.removeParticipant(index: indexToRemove) - self.isShowPopup.toggle() - indexToRemove = -1 - }) - .background(.black.opacity(0.65)) - .onTapGesture { - self.isShowPopup.toggle() - indexToRemove = -1 + .background(.black.opacity(0.65)) + .onTapGesture { + self.isShowPopup.toggle() + indexToRemove = -1 + } } } + .navigationBarHidden(true) } - .navigationBarHidden(true) } @Sendable private func delayColor() async { @@ -256,5 +265,5 @@ struct ParticipantsListFragment: View { } #Preview { - ParticipantsListFragment(callViewModel: CallViewModel(), isShowParticipantsListFragment: .constant(true)) + ParticipantsListFragment(callViewModel: CallViewModel(), addParticipantsViewModel: AddParticipantsViewModel(), isShowParticipantsListFragment: .constant(true)) } diff --git a/Linphone/UI/Call/ViewModel/CallViewModel.swift b/Linphone/UI/Call/ViewModel/CallViewModel.swift index 458053ad6..bd849537b 100644 --- a/Linphone/UI/Call/ViewModel/CallViewModel.swift +++ b/Linphone/UI/Call/ViewModel/CallViewModel.swift @@ -25,6 +25,8 @@ import Combine // swiftlint:disable type_body_length class CallViewModel: ObservableObject { + static let TAG = "[CallViewModel]" + var coreContext = CoreContext.shared var telecomManager = TelecomManager.shared @@ -1130,7 +1132,7 @@ class CallViewModel: ObservableObject { let defaultAccount = core.defaultAccount var subject = "" - if (defaultAccount != nil && defaultAccount!.params != nil && defaultAccount!.params!.audioVideoConferenceFactoryAddress != nil) { + if defaultAccount != nil && defaultAccount!.params != nil && defaultAccount!.params!.audioVideoConferenceFactoryAddress != nil { Log.info("[CallViewModel] Merging \(callsCount) calls into a remotely hosted conference") subject = "Remote group call" } else { @@ -1150,5 +1152,26 @@ class CallViewModel: ObservableObject { } } } + + func addParticipants(participantsToAdd: [SelectedAddressModel]) { + var list: [SelectedAddressModel] = [] + for selectedAddr in participantsToAdd { + if let found = list.first(where: { $0.address.weakEqual(address2: selectedAddr.address) }) { + Log.info("\(CallViewModel.TAG) Participant \(found.address.asStringUriOnly()) already in list, skipping") + continue + } + + list.append(selectedAddr) + Log.info("\(CallViewModel.TAG) Added participant \(selectedAddr.address.asStringUriOnly())") + } + + do { + try self.currentCall!.conference?.addParticipants(addresses: list.map { $0.address }) + } catch { + + } + + Log.info("\(CallViewModel.TAG) \(list.count) participants added to conference") + } } // swiftlint:enable type_body_length