From f771bdc79011ac0a672f090140f26fcd5d644843 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Thu, 4 Apr 2024 17:58:30 +0200 Subject: [PATCH] FIx active speaker mode --- Linphone/TelecomManager/TelecomManager.swift | 11 +- Linphone/UI/Call/CallView.swift | 389 ++++++++++-------- .../UI/Call/ViewModel/CallViewModel.swift | 111 +++-- .../ContactInnerActionsFragment.swift | 2 +- .../Fragments/ContactInnerFragment.swift | 4 +- Linphone/UI/Main/ContentView.swift | 2 +- .../Model/ConversationModel.swift | 2 +- .../History/Fragments/DialerBottomSheet.swift | 2 +- .../Fragments/HistoryContactFragment.swift | 8 +- .../Fragments/HistoryListFragment.swift | 43 +- .../History/Fragments/StartCallFragment.swift | 4 +- 11 files changed, 366 insertions(+), 212 deletions(-) diff --git a/Linphone/TelecomManager/TelecomManager.swift b/Linphone/TelecomManager/TelecomManager.swift index 3cfd68bc0..b4655f5bc 100644 --- a/Linphone/TelecomManager/TelecomManager.swift +++ b/Linphone/TelecomManager/TelecomManager.swift @@ -50,6 +50,7 @@ class TelecomManager: ObservableObject { @Published var isPausedByRemote: Bool = false @Published var refreshCallViewModel: Bool = false @Published var remainingCall: Bool = false + @Published var callConnected: Bool = false var actionToFulFill: CXCallAction? var callkitAudioSessionActivated: Bool? @@ -155,10 +156,10 @@ class TelecomManager: ObservableObject { } } - func doCallWithCore(addr: Address, isVideo: Bool) { + func doCallWithCore(addr: Address, isVideo: Bool, isConference: Bool) { CoreContext.shared.doOnCoreQueue { core in do { - try self.startCallCallKit(core: core, addr: addr, isSas: false, isVideo: isVideo, isConference: false) + try self.startCallCallKit(core: core, addr: addr, isSas: false, isVideo: isVideo, isConference: isConference) } catch { Log.error("[TelecomManager] unable to create address for a new outgoing call : \(addr) \(error) ") } @@ -213,6 +214,7 @@ class TelecomManager: ObservableObject { lcallParams.mediaEncryption = .ZRTP } if isConference { + lcallParams.videoEnabled = true /* if (ConferenceWaitingRoomViewModel.sharedModel.joinLayout.value! != .AudioOnly) { lcallParams.videoEnabled = true lcallParams.videoDirection = ConferenceWaitingRoomViewModel.sharedModel.isVideoEnabled.value == true ? .SendRecv : .RecvOnly @@ -439,6 +441,10 @@ class TelecomManager: ObservableObject { default: self.isPausedByRemote = false } + + if (cstate == Call.State.Connected) { + self.callConnected = true + } } if call.userData == nil { @@ -596,6 +602,7 @@ class TelecomManager: ObservableObject { self.callInProgress = false self.callDisplayed = false self.callStarted = false + self.callConnected = false } } else { if core.calls.last != nil { diff --git a/Linphone/UI/Call/CallView.swift b/Linphone/UI/Call/CallView.swift index cf65931df..9b4a27fdd 100644 --- a/Linphone/UI/Call/CallView.swift +++ b/Linphone/UI/Call/CallView.swift @@ -46,7 +46,7 @@ struct CallView: View { @State var maxBottomSheetHeight: CGFloat = 0.5 @State private var pointingUp: CGFloat = 0.0 @State private var currentOffset: CGFloat = 0.0 - @State private var viewIsDisplayed = false + @State var displayVideo = false @Binding var fullscreenVideo: Bool @Binding var isShowCallsListFragment: Bool @@ -485,64 +485,10 @@ struct CallView: View { Spacer() } - } else { - VStack { - Spacer() - ZStack { - if callViewModel.activeSpeakerParticipant?.address != nil { - let addressFriend = contactsManager.getFriendWithAddress(address: callViewModel.activeSpeakerParticipant!.address) - - let contactAvatarModel = addressFriend != nil - ? ContactsManager.shared.avatarListModel.first(where: { - ($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy) - && $0.friend!.name == addressFriend!.name - && $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly() - }) - : ContactAvatarModel(friend: nil, name: "", withPresence: false) - - if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty { - if contactAvatarModel != nil { - Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 200, hidePresence: true) - } - } else { - if callViewModel.activeSpeakerParticipant!.address.displayName != nil { - Image(uiImage: contactsManager.textToImage( - firstName: callViewModel.activeSpeakerParticipant!.address.displayName!, - lastName: callViewModel.activeSpeakerParticipant!.address.displayName!.components(separatedBy: " ").count > 1 - ? callViewModel.activeSpeakerParticipant!.address.displayName!.components(separatedBy: " ")[1] - : "")) - .resizable() - .frame(width: 200, height: 200) - .clipShape(Circle()) - - } else { - Image(uiImage: contactsManager.textToImage( - firstName: callViewModel.activeSpeakerParticipant!.address.username ?? "Username Error", - lastName: callViewModel.activeSpeakerParticipant!.address.username!.components(separatedBy: " ").count > 1 - ? callViewModel.activeSpeakerParticipant!.address.username!.components(separatedBy: " ")[1] - : "")) - .resizable() - .frame(width: 200, height: 200) - .clipShape(Circle()) - } - - } - } else { - Image("profil-picture-default") - .resizable() - .frame(width: 200, height: 200) - .clipShape(Circle()) - } - } - - Spacer() - } - } - - if !callViewModel.isConference { + LinphoneVideoViewHolder { view in coreContext.doOnCoreQueue { core in - core.nativeVideoWindowId = UnsafeMutableRawPointer(Unmanaged.passRetained(view).toOpaque()) + core.nativeVideoWindow = view } } .frame( @@ -584,26 +530,80 @@ struct CallView: View { maxHeight: fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom : geometry.size.height - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78) - 40 - 20 + geometry.safeAreaInsets.bottom ) } - } else { - /* - if !viewIsDisplayed { - VStack { - - } - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - viewIsDisplayed = true + } else if callViewModel.isConference && !telecomManager.outgoingCallStarted && callViewModel.activeSpeakerParticipant != nil { + VStack { + Spacer() + ZStack { + if callViewModel.activeSpeakerParticipant?.address != nil { + let addressFriend = contactsManager.getFriendWithAddress(address: callViewModel.activeSpeakerParticipant!.address) + + let contactAvatarModel = addressFriend != nil + ? ContactsManager.shared.avatarListModel.first(where: { + ($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy) + && $0.friend!.name == addressFriend!.name + && $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly() + }) + : ContactAvatarModel(friend: nil, name: "", withPresence: true) + + if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty { + if contactAvatarModel != nil { + Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 200, hidePresence: false) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + displayVideo = true + } + } + } + } else { + if callViewModel.activeSpeakerParticipant!.address.displayName != nil { + Image(uiImage: contactsManager.textToImage( + firstName: callViewModel.activeSpeakerParticipant!.address.displayName!, + lastName: callViewModel.activeSpeakerParticipant!.address.displayName!.components(separatedBy: " ").count > 1 + ? callViewModel.activeSpeakerParticipant!.address.displayName!.components(separatedBy: " ")[1] + : "")) + .resizable() + .frame(width: 200, height: 200) + .clipShape(Circle()) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + displayVideo = true + } + } + + } else { + Image(uiImage: contactsManager.textToImage( + firstName: callViewModel.activeSpeakerParticipant!.address.username ?? "Username Error", + lastName: callViewModel.activeSpeakerParticipant!.address.username!.components(separatedBy: " ").count > 1 + ? callViewModel.activeSpeakerParticipant!.address.username!.components(separatedBy: " ")[1] + : "")) + .resizable() + .frame(width: 200, height: 200) + .clipShape(Circle()) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + displayVideo = true + } + } + } + + } + } else { + Image("profil-picture-default") + .resizable() + .frame(width: 200, height: 200) + .clipShape(Circle()) } } + + Spacer() } - if viewIsDisplayed && (callViewModel.receiveVideo || telecomManager.remoteConfVideo) { - */ - if (callViewModel.receiveVideo || telecomManager.remoteConfVideo) && !telecomManager.outgoingCallStarted { + if telecomManager.remoteConfVideo && !telecomManager.outgoingCallStarted && callViewModel.activeSpeakerParticipant != nil && displayVideo { LinphoneVideoViewHolder { view in - coreContext.doOnCoreQueue { core in - //core.nativeVideoWindow = view - core.nativeVideoWindowId = UnsafeMutableRawPointer(Unmanaged.passRetained(view).toOpaque()) + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + coreContext.doOnCoreQueue { core in + core.nativeVideoWindow = view + } } } .frame( @@ -623,35 +623,22 @@ struct CallView: View { fullscreenVideo.toggle() } } - - /* - HStack { - Spacer() - VStack { - Spacer() - LinphoneVideoViewHolder { view in - coreContext.doOnCoreQueue { core in - core.nativePreviewWindow = view - } - } - .frame(width: angleDegree == 0 ? 120*1.2 : 160*1.2, height: angleDegree == 0 ? 160*1.2 : 120*1.2) - .cornerRadius(20) - .padding(10) - .padding(.trailing, abs(angleDegree/2)) - } - } - .frame( - maxWidth: fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.width : geometry.size.width - 8, - maxHeight: fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom : geometry.size.height - (minBottomSheetHeight * geometry.size.height > 80 ? minBottomSheetHeight * geometry.size.height : 78) - 40 - 20 + geometry.safeAreaInsets.bottom - ) - */ } - if !telecomManager.outgoingCallStarted { + if callViewModel.isConference { HStack { Spacer() VStack { Spacer() + + Text(callViewModel.activeSpeakerName) + .frame(maxWidth: .infinity, alignment: .leading) + .foregroundStyle(Color.white) + .default_text_style_500(styleSize: 20) + .lineLimit(1) + .padding(.horizontal, 10) + .padding(.bottom, 6) + ScrollView(.horizontal) { HStack { ZStack { @@ -664,6 +651,20 @@ struct CallView: View { Spacer() } + .frame(width: 140, height: 140) + + if callViewModel.videoDisplayed { + LinphoneVideoViewHolder { view in + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + coreContext.doOnCoreQueue { core in + core.nativePreviewWindow = view + } + } + } + .frame(width: angleDegree == 0 ? 120*1.2 : 160*1.2, height: angleDegree == 0 ? 160*1.2 : 120*1.2) + .scaledToFill() + .clipped() + } VStack(alignment: .leading) { Spacer() @@ -678,44 +679,50 @@ struct CallView: View { .padding(.bottom, 6) } } - .frame(maxWidth: .infinity) - - LinphoneVideoViewHolder { view in - coreContext.doOnCoreQueue { core in - core.nativePreviewWindow = view - } - } + .frame(width: 140, height: 140) } .frame(width: 140, height: 140) .background(Color.gray600) .cornerRadius(20) ForEach(0.. 80 ? minBottomSheetHeight * geometry.size.height : 78) - 40 - 20 + geometry.safeAreaInsets.bottom ) .padding(.bottom, 10) + .padding(.leading, -10) } } @@ -773,6 +781,11 @@ struct CallView: View { Spacer() } + .onDisappear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + callViewModel.getConference() + } + } .background(.clear) .frame( maxWidth: fullscreenVideo && !telecomManager.isPausedByRemote ? geometry.size.width : geometry.size.width - 8, @@ -1186,29 +1199,54 @@ struct CallView: View { } .frame(width: geo.size.width * 0.25, height: geo.size.width * 0.25) - VStack { - Button { - callViewModel.toggleRecording() - } label: { - HStack { - Image("record-fill") - .renderingMode(.template) - .resizable() - .foregroundStyle((callViewModel.isPaused || telecomManager.isPausedByRemote) ? Color.gray500 : .white) - .frame(width: 32, height: 32) + if !callViewModel.isConference { + VStack { + Button { + callViewModel.toggleRecording() + } label: { + HStack { + Image("record-fill") + .renderingMode(.template) + .resizable() + .foregroundStyle((callViewModel.isPaused || telecomManager.isPausedByRemote) ? Color.gray500 : .white) + .frame(width: 32, height: 32) + } } + .buttonStyle(PressedButtonStyle()) + .frame(width: 60, height: 60) + .background((callViewModel.isPaused || telecomManager.isPausedByRemote) ? .white : (callViewModel.isRecording ? Color.redDanger500 : Color.gray500)) + .cornerRadius(40) + .disabled(callViewModel.isPaused || telecomManager.isPausedByRemote) + + Text("Record") + .foregroundStyle(.white) + .default_text_style(styleSize: 15) } - .buttonStyle(PressedButtonStyle()) - .frame(width: 60, height: 60) - .background((callViewModel.isPaused || telecomManager.isPausedByRemote) ? .white : (callViewModel.isRecording ? Color.redDanger500 : Color.gray500)) - .cornerRadius(40) - .disabled(callViewModel.isPaused || telecomManager.isPausedByRemote) - - Text("Record") - .foregroundStyle(.white) - .default_text_style(styleSize: 15) + .frame(width: geo.size.width * 0.25, height: geo.size.width * 0.25) + } else { + VStack { + Button { + } label: { + HStack { + Image("record-fill") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray500) + .frame(width: 32, height: 32) + } + } + .buttonStyle(PressedButtonStyle()) + .frame(width: 60, height: 60) + .background(.white) + .cornerRadius(40) + .disabled(true) + + Text("Record") + .foregroundStyle(.white) + .default_text_style(styleSize: 15) + } + .frame(width: geo.size.width * 0.25, height: geo.size.width * 0.25) } - .frame(width: geo.size.width * 0.25, height: geo.size.width * 0.25) VStack { Button { @@ -1403,29 +1441,54 @@ struct CallView: View { } .frame(width: geo.size.width * 0.125, height: geo.size.width * 0.125) - VStack { - Button { - callViewModel.toggleRecording() - } label: { - HStack { - Image("record-fill") - .renderingMode(.template) - .resizable() - .foregroundStyle((callViewModel.isPaused || telecomManager.isPausedByRemote) ? Color.gray500 : .white) - .frame(width: 32, height: 32) + if !callViewModel.isConference { + VStack { + Button { + callViewModel.toggleRecording() + } label: { + HStack { + Image("record-fill") + .renderingMode(.template) + .resizable() + .foregroundStyle((callViewModel.isPaused || telecomManager.isPausedByRemote) ? Color.gray500 : .white) + .frame(width: 32, height: 32) + } } + .buttonStyle(PressedButtonStyle()) + .frame(width: 60, height: 60) + .background((callViewModel.isPaused || telecomManager.isPausedByRemote) ? .white : (callViewModel.isRecording ? Color.redDanger500 : Color.gray500)) + .cornerRadius(40) + .disabled(callViewModel.isPaused || telecomManager.isPausedByRemote) + + Text("Record") + .foregroundStyle(.white) + .default_text_style(styleSize: 15) } - .buttonStyle(PressedButtonStyle()) - .frame(width: 60, height: 60) - .background((callViewModel.isPaused || telecomManager.isPausedByRemote) ? .white : (callViewModel.isRecording ? Color.redDanger500 : Color.gray500)) - .cornerRadius(40) - .disabled(callViewModel.isPaused || telecomManager.isPausedByRemote) - - Text("Record") - .foregroundStyle(.white) - .default_text_style(styleSize: 15) + .frame(width: geo.size.width * 0.125, height: geo.size.width * 0.125) + } else { + VStack { + Button { + } label: { + HStack { + Image("record-fill") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray500) + .frame(width: 32, height: 32) + } + } + .buttonStyle(PressedButtonStyle()) + .frame(width: 60, height: 60) + .background(.white) + .cornerRadius(40) + .disabled(true) + + Text("Record") + .foregroundStyle(.white) + .default_text_style(styleSize: 15) + } + .frame(width: geo.size.width * 0.125, height: geo.size.width * 0.125) } - .frame(width: geo.size.width * 0.125, height: geo.size.width * 0.125) } .frame(height: geo.size.height * 0.15) .padding(.horizontal, 20) diff --git a/Linphone/UI/Call/ViewModel/CallViewModel.swift b/Linphone/UI/Call/ViewModel/CallViewModel.swift index 38ef4a84b..eb8b1f1a7 100644 --- a/Linphone/UI/Call/ViewModel/CallViewModel.swift +++ b/Linphone/UI/Call/ViewModel/CallViewModel.swift @@ -47,9 +47,9 @@ class CallViewModel: ObservableObject { @Published var isTransferInsteadCall: Bool = false @Published var isConference: Bool = false @Published var videoDisplayed: Bool = false - @Published var receiveVideo: Bool = false @Published var participantList: [ParticipantModel] = [] @Published var activeSpeakerParticipant: ParticipantModel? = nil + @Published var activeSpeakerName: String = "" @Published var myParticipantModel: ParticipantModel? = nil @@ -80,7 +80,7 @@ class CallViewModel: ObservableObject { } } - func disableAVAudioSession(){ + func disableAVAudioSession() { do { try AVAudioSession.sharedInstance().setActive(false) } catch _ { @@ -117,6 +117,14 @@ class CallViewModel: ObservableObject { let authToken = self.currentCall!.authenticationToken let isDeviceTrusted = self.currentCall!.authenticationTokenVerified && authToken != nil self.isRemoteDeviceTrusted = self.telecomManager.callInProgress ? isDeviceTrusted : false + self.activeSpeakerParticipant = nil + + do { + let params = try core.createCallParams(call: self.currentCall) + self.videoDisplayed = params.videoDirection == MediaDirection.SendRecv + } catch { + + } self.getCallsList() self.getConference() @@ -139,28 +147,69 @@ class CallViewModel: ObservableObject { func getConference() { coreContext.doOnCoreQueue { core in - //conf = self.currentCall?.conference != nil ? self.currentCall!.conference! : core.findConferenceInformationFromUri(uri: (self.currentCall?.remoteContactAddress)!) - if self.currentCall?.remoteContactAddress != nil { - let conf = core.findConferenceInformationFromUri(uri: (self.currentCall?.remoteContactAddress)!) + if self.currentCall?.conference != nil { + let conf = self.currentCall!.conference! + self.isConference = true DispatchQueue.main.async { - self.isConference = conf != nil - if self.isConference { - self.displayName = conf?.subject ?? "" - self.participantList = [] - conf?.participantInfos.forEach({ participantInfo in - if participantInfo.address != nil { - if participantInfo.address!.equal(address2: (self.currentCall?.callLog?.localAddress!)!) { - self.myParticipantModel = ParticipantModel(address: participantInfo.address!) - } else { - if self.activeSpeakerParticipant != nil && !participantInfo.address!.equal(address2: self.activeSpeakerParticipant!.address) { - self.participantList.append(ParticipantModel(address: participantInfo.address!)) - } - } - } - }) - self.addConferenceCallBacks() + self.displayName = conf.subject ?? "" + self.participantList = [] + + if self.currentCall?.callLog?.localAddress != nil { + self.myParticipantModel = ParticipantModel(address: self.currentCall!.callLog!.localAddress!) } + + if conf.activeSpeakerParticipantDevice?.address != nil { + self.activeSpeakerParticipant = ParticipantModel(address: conf.activeSpeakerParticipantDevice!.address!) + } else if conf.participantList.first?.address != nil { + self.activeSpeakerParticipant = ParticipantModel(address: conf.participantList.first!.address!) + } else { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + self.getConference() + } + } + + if self.activeSpeakerParticipant != nil { + let friend = ContactsManager.shared.getFriendWithAddress(address: self.activeSpeakerParticipant!.address) + if friend != nil && friend!.address != nil && friend!.address!.displayName != nil { + self.activeSpeakerName = friend!.address!.displayName! + } else { + if self.activeSpeakerParticipant!.address.displayName != nil { + self.activeSpeakerName = self.activeSpeakerParticipant!.address.displayName! + } else if self.activeSpeakerParticipant!.address.username != nil { + self.activeSpeakerName = self.activeSpeakerParticipant!.address.username! + } + } + } + + conf.participantList.forEach({ participant in + self.participantList.append(ParticipantModel(address: participant.address!)) + }) + + self.addConferenceCallBacks() } + } else if self.currentCall?.remoteContactAddress != nil { + let conf = core.findConferenceInformationFromUri(uri: (self.currentCall?.remoteContactAddress)!) + DispatchQueue.main.async { + self.isConference = conf != nil + if self.isConference { + self.displayName = conf?.subject ?? "" + self.participantList = [] + + conf?.participantInfos.forEach({ participantInfo in + if participantInfo.address != nil { + if participantInfo.address!.equal(address2: (self.currentCall?.callLog?.localAddress!)!) { + self.myParticipantModel = ParticipantModel(address: participantInfo.address!) + } else { + if self.activeSpeakerParticipant != nil && !participantInfo.address!.equal(address2: self.activeSpeakerParticipant!.address) { + self.participantList.append(ParticipantModel(address: participantInfo.address!)) + } + } + } + }) + + self.addConferenceCallBacks() + } + } } } } @@ -169,14 +218,24 @@ class CallViewModel: ObservableObject { coreContext.doOnCoreQueue { core in self.mConferenceSuscriptions.insert( self.currentCall?.conference?.publisher?.onActiveSpeakerParticipantDevice?.postOnMainQueue {(cbValue: (conference: Conference, participantDevice: ParticipantDevice)) in - let direction = cbValue.participantDevice.getStreamCapability(streamType: StreamType.Video) - - self.receiveVideo = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly - if cbValue.participantDevice.address != nil { let activeSpeakerParticipantTmp = self.activeSpeakerParticipant self.activeSpeakerParticipant = ParticipantModel(address: cbValue.participantDevice.address!) + + if self.activeSpeakerParticipant != nil { + let friend = ContactsManager.shared.getFriendWithAddress(address: self.activeSpeakerParticipant!.address) + if friend != nil && friend!.address != nil && friend!.address!.displayName != nil { + self.activeSpeakerName = friend!.address!.displayName! + } else { + if self.activeSpeakerParticipant!.address.displayName != nil { + self.activeSpeakerName = self.activeSpeakerParticipant!.address.displayName! + } else if self.activeSpeakerParticipant!.address.username != nil { + self.activeSpeakerName = self.activeSpeakerParticipant!.address.username! + } + } + } + if self.activeSpeakerParticipant != nil && ((activeSpeakerParticipantTmp != nil && !activeSpeakerParticipantTmp!.address.equal(address2: self.activeSpeakerParticipant!.address)) || ( activeSpeakerParticipantTmp == nil)) { @@ -184,7 +243,7 @@ class CallViewModel: ObservableObject { self.participantList = [] cbValue.conference.participantList.forEach({ participant in if participant.address != nil && !cbValue.conference.isMe(uri: participant.address!) { - if !cbValue.conference.isMe(uri: participant.address!) && !participant.address!.equal(address2: self.activeSpeakerParticipant!.address) { + if !cbValue.conference.isMe(uri: participant.address!) { self.participantList.append(ParticipantModel(address: participant.address!)) } } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift index be78afc16..9d50cfc1e 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift @@ -94,7 +94,7 @@ struct ContactInnerActionsFragment: View { .onTapGesture { withAnimation { telecomManager.doCallWithCore( - addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index], isVideo: false + addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index], isVideo: false, isConference: false ) } } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift index 5dd1b1787..7974d0a88 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift @@ -158,7 +158,7 @@ struct ContactInnerFragment: View { Spacer() Button(action: { - telecomManager.doCallWithCore(addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.address!, isVideo: false) + telecomManager.doCallWithCore(addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.address!, isVideo: false, isConference: false) }, label: { VStack { HStack(alignment: .center) { @@ -208,7 +208,7 @@ struct ContactInnerFragment: View { Spacer() Button(action: { - telecomManager.doCallWithCore(addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.address!, isVideo: true) + telecomManager.doCallWithCore(addr: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.address!, isVideo: true, isConference: false) }, label: { VStack { HStack(alignment: .center) { diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index bce817c6e..412541b28 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -856,7 +856,7 @@ struct ContentView: View { } } - if telecomManager.callInProgress && telecomManager.callDisplayed { + if telecomManager.callDisplayed && ((telecomManager.callInProgress && telecomManager.outgoingCallStarted) || telecomManager.callConnected) { CallView(callViewModel: callViewModel, fullscreenVideo: $fullscreenVideo, isShowCallsListFragment: $isShowCallsListFragment, isShowStartCallFragment: $isShowStartCallFragment) .zIndex(3) .transition(.scale.combined(with: .move(edge: .top))) diff --git a/Linphone/UI/Main/Conversations/Model/ConversationModel.swift b/Linphone/UI/Main/Conversations/Model/ConversationModel.swift index a1090a043..35aa5dd28 100644 --- a/Linphone/UI/Main/Conversations/Model/ConversationModel.swift +++ b/Linphone/UI/Main/Conversations/Model/ConversationModel.swift @@ -129,7 +129,7 @@ class ConversationModel: ObservableObject { coreContext.doOnCoreQueue { _ in if self.chatRoom.peerAddress != nil { TelecomManager.shared.doCallWithCore( - addr: self.chatRoom.peerAddress!, isVideo: false + addr: self.chatRoom.peerAddress!, isVideo: false, isConference: false ) } } diff --git a/Linphone/UI/Main/History/Fragments/DialerBottomSheet.swift b/Linphone/UI/Main/History/Fragments/DialerBottomSheet.swift index 0fadeb5d0..267c8aded 100644 --- a/Linphone/UI/Main/History/Fragments/DialerBottomSheet.swift +++ b/Linphone/UI/Main/History/Fragments/DialerBottomSheet.swift @@ -434,7 +434,7 @@ struct DialerBottomSheet: View { if !startCallViewModel.searchField.isEmpty { do { let address = try Factory.Instance.createAddress(addr: String("sip:" + startCallViewModel.searchField + "@" + startCallViewModel.domain)) - telecomManager.doCallWithCore(addr: address, isVideo: false) + telecomManager.doCallWithCore(addr: address, isVideo: false, isConference: false) } catch { } diff --git a/Linphone/UI/Main/History/Fragments/HistoryContactFragment.swift b/Linphone/UI/Main/History/Fragments/HistoryContactFragment.swift index 9c427a317..71062797b 100644 --- a/Linphone/UI/Main/History/Fragments/HistoryContactFragment.swift +++ b/Linphone/UI/Main/History/Fragments/HistoryContactFragment.swift @@ -388,11 +388,11 @@ struct HistoryContactFragment: View { Button(action: { if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { telecomManager.doCallWithCore( - addr: historyViewModel.displayedCall!.toAddress!, isVideo: false + addr: historyViewModel.displayedCall!.toAddress!, isVideo: false, isConference: false ) } else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil { telecomManager.doCallWithCore( - addr: historyViewModel.displayedCall!.fromAddress!, isVideo: false + addr: historyViewModel.displayedCall!.fromAddress!, isVideo: false, isConference: false ) } }, label: { @@ -448,11 +448,11 @@ struct HistoryContactFragment: View { Button(action: { if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { telecomManager.doCallWithCore( - addr: historyViewModel.displayedCall!.toAddress!, isVideo: true + addr: historyViewModel.displayedCall!.toAddress!, isVideo: true, isConference: false ) } else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil { telecomManager.doCallWithCore( - addr: historyViewModel.displayedCall!.fromAddress!, isVideo: true + addr: historyViewModel.displayedCall!.fromAddress!, isVideo: true, isConference: false ) } }, label: { diff --git a/Linphone/UI/Main/History/Fragments/HistoryListFragment.swift b/Linphone/UI/Main/History/Fragments/HistoryListFragment.swift index 0c4bc0d05..87c80a253 100644 --- a/Linphone/UI/Main/History/Fragments/HistoryListFragment.swift +++ b/Linphone/UI/Main/History/Fragments/HistoryListFragment.swift @@ -165,15 +165,7 @@ struct HistoryListFragment: View { TapGesture() .onEnded { _ in withAnimation { - if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil { - telecomManager.doCallWithCore( - addr: historyListViewModel.callLogs[index].toAddress!, isVideo: false - ) - } else if historyListViewModel.callLogs[index].fromAddress != nil { - telecomManager.doCallWithCore( - addr: historyListViewModel.callLogs[index].fromAddress!, isVideo: false - ) - } + doCall(index: index) historyViewModel.displayedCall = nil } } @@ -217,6 +209,39 @@ struct HistoryListFragment: View { .navigationTitle("") .navigationBarHidden(true) } + + func doCall(index: Int) { + if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil { + if historyListViewModel.callLogs[index].toAddress!.asStringUriOnly().hasPrefix("sip:conference-focus@sip.linphone.org") { + do { + //let reudumatin = try Factory.Instance.createAddress(addr: "sip:conference-focus@sip.linphone.org;conf-id=8~YNkpFOv;gr=0ee3f37f-6df2-0071-bb9a-a4e24be30135") + let reutest = try Factory.Instance.createAddress(addr: "sip:conference-focus@sip.linphone.org;conf-id=iVs8XshC~;gr=0ee3f37f-6df2-0071-bb9a-a4e24be30135") + + telecomManager.doCallWithCore( + addr: reutest, isVideo: false, isConference: true + ) + } catch {} + } else { + telecomManager.doCallWithCore( + addr: historyListViewModel.callLogs[index].toAddress!, isVideo: false, isConference: false + ) + } + } else if historyListViewModel.callLogs[index].fromAddress != nil { + if historyListViewModel.callLogs[index].fromAddress!.asStringUriOnly().hasPrefix("sip:conference-focus@sip.linphone.org") { + do { + //let reudumatin = try Factory.Instance.createAddress(addr: "sip:conference-focus@sip.linphone.org;conf-id=8~YNkpFOv;gr=0ee3f37f-6df2-0071-bb9a-a4e24be30135") + let reutest = try Factory.Instance.createAddress(addr: "sip:conference-focus@sip.linphone.org;conf-id=iVs8XshC~;gr=0ee3f37f-6df2-0071-bb9a-a4e24be30135") + telecomManager.doCallWithCore( + addr: reutest, isVideo: false, isConference: true + ) + } catch {} + } else { + telecomManager.doCallWithCore( + addr: historyListViewModel.callLogs[index].fromAddress!, isVideo: false, isConference: false + ) + } + } + } } #Preview { diff --git a/Linphone/UI/Main/History/Fragments/StartCallFragment.swift b/Linphone/UI/Main/History/Fragments/StartCallFragment.swift index 7eea3b63f..37a5f2a4f 100644 --- a/Linphone/UI/Main/History/Fragments/StartCallFragment.swift +++ b/Linphone/UI/Main/History/Fragments/StartCallFragment.swift @@ -219,7 +219,7 @@ struct StartCallFragment: View { withAnimation { isShowStartCallFragment.toggle() - telecomManager.doCallWithCore(addr: addr, isVideo: false) + telecomManager.doCallWithCore(addr: addr, isVideo: false, isConference: false) } } }) @@ -305,7 +305,7 @@ struct StartCallFragment: View { isShowStartCallFragment.toggle() if contactsManager.lastSearchSuggestions[index].address != nil { telecomManager.doCallWithCore( - addr: contactsManager.lastSearchSuggestions[index].address!, isVideo: false + addr: contactsManager.lastSearchSuggestions[index].address!, isVideo: false, isConference: false ) } }