FIx active speaker mode

This commit is contained in:
Benoit Martins 2024-04-04 17:58:30 +02:00
parent 027cb1ec2d
commit f771bdc790
11 changed files with 366 additions and 212 deletions

View file

@ -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 {

View file

@ -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..<callViewModel.participantList.count, id: \.self) { index in
ZStack {
VStack {
Spacer()
if callViewModel.activeSpeakerParticipant != nil && !callViewModel.participantList[index].address.equal(address2: callViewModel.activeSpeakerParticipant!.address) {
ZStack {
VStack {
Spacer()
Avatar(contactAvatarModel: callViewModel.participantList[index].avatarModel, avatarSize: 50)
Spacer()
}
Avatar(contactAvatarModel: callViewModel.participantList[index].avatarModel, avatarSize: 50)
LinphoneVideoViewHolder { view in
coreContext.doOnCoreQueue { core in
let participantVideo = core.currentCall?.conference?.participantList.first(where: {$0.address!.equal(address2: callViewModel.participantList[index].address)})
if participantVideo != nil && participantVideo!.devices.first != nil {
participantVideo!.devices.first!.nativeVideoWindowId = UnsafeMutableRawPointer(Unmanaged.passRetained(view).toOpaque())
}
}
}
VStack(alignment: .leading) {
Spacer()
Text(callViewModel.participantList[index].name)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundStyle(Color.white)
.default_text_style_500(styleSize: 14)
.lineLimit(1)
.padding(.horizontal, 10)
.padding(.bottom, 6)
}
.frame(maxWidth: .infinity)
Spacer()
}
VStack(alignment: .leading) {
Spacer()
Text(callViewModel.participantList[index].name)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundStyle(Color.white)
.default_text_style_500(styleSize: 14)
.lineLimit(1)
.padding(.horizontal, 10)
.padding(.bottom, 6)
}
.frame(maxWidth: .infinity)
.frame(width: 140, height: 140)
.background(Color.gray600)
.cornerRadius(20)
}
.frame(width: 140, height: 140)
.background(Color.gray600)
.cornerRadius(20)
}
}
}
@ -726,6 +733,7 @@ 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
)
.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)

View file

@ -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!))
}
}

View file

@ -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
)
}
}

View file

@ -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) {

View file

@ -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)))

View file

@ -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
)
}
}

View file

@ -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 {
}

View file

@ -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: {

View file

@ -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 {

View file

@ -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
)
}
}