Incoming calls from Conference serveur handling - (CallKit)

This commit is contained in:
Christophe Deschamps 2022-06-10 16:50:34 +02:00
parent 64d33a67fb
commit ecad9c86b3
4 changed files with 96 additions and 14 deletions

View file

@ -206,6 +206,15 @@ import AVFoundation
Log.directLog(BCTBX_LOG_MESSAGE, text: "Voice recording in progress, stopping it befoce accepting the call.")
chatView.stopVoiceRecording()
}
if (call.callLog?.wasConference() == true) {
// Prevent incoming group call to start in audio only layout
// Do the same as the conference waiting room
callParams.videoEnabled = true
callParams.videoDirection = Core.get().videoActivationPolicy?.automaticallyInitiate == true ? .SendRecv : .RecvOnly
Log.i("[Context] Enabling video on call params to prevent audio-only layout when answering")
}
try call.acceptWithParams(params: callParams)
} catch {
Log.directLog(BCTBX_LOG_ERROR, text: "accept call failed \(error)")
@ -430,6 +439,11 @@ import AVFoundation
CallManager.instance().endCallkit = false
}
}
func isConferenceCall(call:Call) -> Bool {
let remoteAddress = call.remoteAddress?.asStringUriOnly()
return remoteAddress?.contains("focus") == true || remoteAddress?.contains("audiovideo") == true
}
func onCallStateChanged(core: Core, call: Call, state cstate: Call.State, message: String) {
let callLog = call.callLog
@ -452,9 +466,31 @@ import AVFoundation
switch cstate {
case .IncomingReceived:
let addr = call.remoteAddress;
let displayName = FastAddressBook.displayName(for: addr?.getCobject) ?? "Unknown"
let addr = call.remoteAddress
var displayName = ""
let isConference = isConferenceCall(call: call)
let isEarlyConference = isConference && CallsViewModel.shared.currentCallData.value??.isConferenceCall.value != true // Conference info not be received yet.
if (isConference) {
if (isEarlyConference) {
displayName = VoipTexts.conference_incoming_title
} else {
displayName = "\(VoipTexts.conference_incoming_title): \(CallsViewModel.shared.currentCallData.value??.remoteConferenceSubject.value ?? "") (\(CallsViewModel.shared.currentCallData.value??.conferenceParticipantsCountLabel.value ?? ""))"
}
} else {
displayName = FastAddressBook.displayName(for: addr?.getCobject) ?? "Unknown"
}
if (CallManager.callKitEnabled()) {
if (isEarlyConference) {
CallsViewModel.shared.currentCallData.readCurrentAndObserve { _ in
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
if (uuid != nil) {
displayName = "\(VoipTexts.conference_incoming_title): \(CallsViewModel.shared.currentCallData.value??.remoteConferenceSubject.value ?? "") (\(CallsViewModel.shared.currentCallData.value??.conferenceParticipantsCountLabel.value ?? ""))"
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
}
}
}
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
if (uuid != nil) {
// Tha app is now registered, updated the call already existed.

View file

@ -111,10 +111,10 @@ import UIKit
static let conference_info_confirm_removal_delete = NSLocalizedString("Delete",comment:"")
static let conference_last_user = NSLocalizedString("All other participants have left the group call",comment:"")
static let conference_first_to_join = NSLocalizedString("You're the first to join the group call",comment:"")
static let conference_incoming_title = NSLocalizedString("Incoming group call",comment:"")
static let conference_participants_title = NSLocalizedString("%d participants",comment:"")
// Call Stats
static let call_stats_audio = "Audio"

View file

@ -32,6 +32,11 @@ class CallData {
let isRemotelyRecorded = MutableLiveData<Bool>()
let isInRemoteConference = MutableLiveData<Bool>()
let remoteConferenceSubject = MutableLiveData<String>()
let isConferenceCall = MediatorLiveData<Bool>()
let conferenceParticipants = MutableLiveData<[Address]>()
let conferenceParticipantsCountLabel = MutableLiveData<String>()
let callKitConferenceLabel = MutableLiveData<String>()
let isOutgoing = MutableLiveData<Bool>()
let isIncoming = MutableLiveData<Bool>()
let callState = MutableLiveData<Call.State>()
@ -58,6 +63,14 @@ class CallData {
}
)
call.addDelegate(delegate: callDelegate!)
remoteConferenceSubject.readCurrentAndObserve { _ in
self.isConferenceCall.value = self.remoteConferenceSubject.value?.count ?? 0 > 0 || self.conferenceParticipants.value?.count ?? 0 > 0
}
conferenceParticipants.readCurrentAndObserve { _ in
self.isConferenceCall.value = self.remoteConferenceSubject.value?.count ?? 0 > 0 || self.conferenceParticipants.value?.count ?? 0 > 0
}
update()
}
@ -86,13 +99,12 @@ class CallData {
isPaused.value = isCallPaused()
isRemotelyPaused.value = isCallRemotelyPaused()
canBePaused.value = canCallBePaused()
let conference = call.conference
isInRemoteConference.value = conference != nil || isCallingAConference()
if (conference != nil) {
remoteConferenceSubject.value = ConferenceViewModel.getConferenceSubject(conference: conference!)
}
updateConferenceInfo()
isOutgoing.value = isOutGoing()
isIncoming.value = isInComing()
if (call.mediaInProgress()) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.update()
@ -103,6 +115,43 @@ class CallData {
callState.value = call.state
}
private func updateConferenceInfo() {
let conference = call.conference
isInRemoteConference.value = conference != nil
if (conference != nil) {
Log.d("[Call] Found conference attached to call")
remoteConferenceSubject.value = ConferenceViewModel.getConferenceSubject(conference: conference!)
Log.d("[Call] Found conference related to this call with subject \(remoteConferenceSubject.value)")
var participantsList:[Address] = []
conference?.participantList.forEach {
$0.address.map {participantsList.append($0)}
}
conferenceParticipants.value = participantsList
conferenceParticipantsCountLabel.value = VoipTexts.conference_participants_title.replacingOccurrences(of:"%d",with:String(participantsList.count))
} else {
if let conferenceAddress = getConferenceAddress(call: call), let conferenceInfo = Core.get().findConferenceInformationFromUri(uri:conferenceAddress) {
Log.d("[Call] Found matching conference info with subject: \(conferenceInfo.subject)")
remoteConferenceSubject.value = conferenceInfo.subject
var participantsList:[Address] = []
conferenceInfo.participants.forEach {
participantsList.append($0)
}
// Add organizer if not in participants list
if let organizer = conferenceInfo.organizer {
if (participantsList.filter { $0.weakEqual(address2: organizer) }.first == nil) {
participantsList.insert(organizer, at:0)
}
conferenceParticipants.value = participantsList
conferenceParticipantsCountLabel.value = VoipTexts.conference_participants_title.replacingOccurrences(of:"%d",with:String(participantsList.count))
}
}
}
}
func getConferenceAddress(call: Call) -> Address? {
let remoteContact = call.remoteContact
return call.dir == .Incoming ? (remoteContact != nil ? Core.get().interpretUrl(url: remoteContact) : nil) : call.remoteAddress
}
func sendDTMF(dtmf:String) {
enteredDTMF.value = enteredDTMF.value! + dtmf
@ -150,8 +199,5 @@ class CallData {
isPaused.value = isCallPaused()
}
func isCallingAConference() -> Bool {
return CallManager.getAppData(call: call.getCobject!)?.isConference == true
}
}

View file

@ -328,7 +328,7 @@ import linphonesw
if (data?.isOutgoing.value == true || data?.isIncoming.value == true) {
PhoneMainView.instance().popView(self.compositeViewDescription())
} else {
if (data!.isCallingAConference()) {
if (data!.isInRemoteConference.value == true) {
PhoneMainView.instance().pop(toView: self.compositeViewDescription())
} else {
PhoneMainView.instance().changeCurrentView(self.compositeViewDescription())