Use Conference object instead of ConferenceScheduler for group call initiation

This commit is contained in:
Benoit Martins 2025-02-20 18:40:41 +01:00
parent 1510a1b045
commit 095705ad37
5 changed files with 75 additions and 62 deletions

View file

@ -430,6 +430,27 @@ class TelecomManager: ObservableObject {
func onCallStateChanged(core: Core, call: Call, state cstate: Call.State, message: String) {
let callLog = call.callLog
let callId = callLog?.callId ?? ""
if cstate == .OutgoingInit && !callInProgress {
if let remoteAddress = call.remoteAddress {
let uuid = UUID()
let name = remoteAddress.asStringUriOnly()
let handle = CXHandle(type: .generic, value: remoteAddress.asStringUriOnly())
let startCallAction = CXStartCallAction(call: uuid, handle: handle)
let transaction = CXTransaction(action: startCallAction)
let callInfo = CallInfo.newOutgoingCallInfo(addr: remoteAddress, isSas: false, displayName: name, isVideo: true, isConference: true)
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
providerDelegate.uuids.updateValue(uuid, forKey: callId)
setHeldOtherCalls(core: core, exceptCallid: callId)
requestTransaction(transaction, action: "startCall")
DispatchQueue.main.async {
withAnimation {
self.callDisplayed = true
}
}
}
}
if cstate == .PushIncomingReceived {
Log.info("PushIncomingReceived in core delegate, display callkit call")
TelecomManager.shared.displayIncomingCall(call: call, handle: "Calling", hasVideo: false, callId: callId, displayName: "Calling")

View file

@ -718,7 +718,7 @@ struct ConversationFragment: View {
}
} else {
Button {
if conversationViewModel.displayedConversationHistorySize > 0 {
if conversationViewModel.displayedConversationHistorySize > 1 {
NotificationCenter.default.post(name: .onScrollToBottom, object: nil)
}
conversationViewModel.sendMessage()

View file

@ -362,15 +362,16 @@ struct UIList: UIViewRepresentable {
NotificationCenter.default.addObserver(forName: .onScrollToBottom, object: nil, queue: nil) { _ in
DispatchQueue.main.async {
if !self.sections.isEmpty {
if self.sections.first != nil
&& parent.conversationViewModel.conversationMessagesSection.first != nil
&& parent.conversationViewModel.displayedConversation != nil
&& self.sections.first!.chatRoomID == parent.conversationViewModel.displayedConversation!.id
&& self.sections.first!.rows.count == parent.conversationViewModel.conversationMessagesSection.first!.rows.count {
self.tableView!.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}
guard !self.sections.isEmpty,
let firstSection = self.sections.first,
let firstConversationSection = parent.conversationViewModel.conversationMessagesSection.first,
let displayedConversation = parent.conversationViewModel.displayedConversation,
let tableView = self.tableView,
firstSection.chatRoomID == displayedConversation.id,
firstSection.rows.count == firstConversationSection.rows.count else {
return
}
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}
}

View file

@ -50,8 +50,8 @@ class ConversationModel: ObservableObject, Identifiable {
@Published var unreadMessagesCount: Int
@Published var avatarModel: ContactAvatarModel
private var conferenceScheduler: ConferenceScheduler?
private var conferenceSchedulerDelegate: ConferenceSchedulerDelegate?
//private var conference: Conference?
private var conferenceDelegate: ConferenceDelegate?
init(chatRoom: ChatRoom) {
self.chatRoom = chatRoom
@ -138,31 +138,24 @@ class ConversationModel: ObservableObject, Identifiable {
conferenceInfo.organizer = account!.params?.identityAddress
conferenceInfo.subject = self.chatRoom.subject ?? "Conference"
var participantsList: [ParticipantInfo] = []
var participantsList: [Address] = []
self.chatRoom.participants.forEach { participant in
do {
let info = try Factory.Instance.createParticipantInfo(address: participant.address!)
// For meetings, all participants must have Speaker role
info.role = Participant.Role.Speaker
participantsList.append(info)
} catch let error {
Log.error(
"\(ConversationModel.TAG) Can't create ParticipantInfo: \(error)"
)
}
participantsList.append(participant.address!)
}
conferenceInfo.addParticipantInfos(participantInfos: participantsList)
Log.info(
"\(ConversationModel.TAG) Creating group call with subject \(self.chatRoom.subject ?? "Conference") and \(participantsList.count) participant(s)"
)
self.conferenceScheduler = try core.createConferenceScheduler(account: account)
if self.conferenceScheduler != nil {
self.conferenceAddDelegate(core: core, conferenceScheduler: self.conferenceScheduler!)
// Will trigger the conference creation/update automatically
self.conferenceScheduler!.info = conferenceInfo
if let conference = LinphoneUtils.createGroupCall(core: core, account: account, subject: self.chatRoom.subject ?? "Conference") {
let callParams = try? core.createCallParams(call: nil)
if let callParams = callParams {
callParams.videoEnabled = true
callParams.videoDirection = .RecvOnly
print("\(ConversationModel.TAG) Inviting \(participantsList.count) participant(s) into newly created conference")
try conference.inviteParticipants(addresses: participantsList, params: callParams)
}
}
} catch let error {
Log.error(
@ -172,38 +165,6 @@ class ConversationModel: ObservableObject, Identifiable {
}
}
func conferenceAddDelegate(core: Core, conferenceScheduler: ConferenceScheduler) {
self.conferenceSchedulerDelegate = ConferenceSchedulerDelegateStub(onStateChanged: { (conferenceScheduler: ConferenceScheduler, state: ConferenceScheduler.State) in
Log.info("\(ConversationModel.TAG) Conference scheduler state is \(state)")
if state == ConferenceScheduler.State.Ready {
conferenceScheduler.removeDelegate(delegate: self.conferenceSchedulerDelegate!)
self.conferenceSchedulerDelegate = nil
let conferenceAddress = conferenceScheduler.info?.uri
if conferenceAddress != nil {
Log.info(
"\(ConversationModel.TAG) Conference info created, address is \(conferenceAddress!.asStringUriOnly())"
)
TelecomManager.shared.doCallWithCore(addr: conferenceAddress!, isVideo: true, isConference: true)
} else {
Log.error("\(ConversationModel.TAG) Conference info URI is null!")
ToastViewModel.shared.toastMessage = "Failed_to_create_group_call_error"
ToastViewModel.shared.displayToast = true
}
} else if state == ConferenceScheduler.State.Error {
conferenceScheduler.removeDelegate(delegate: self.conferenceSchedulerDelegate!)
self.conferenceSchedulerDelegate = nil
Log.error("\(ConversationModel.TAG) Failed to create group call!")
ToastViewModel.shared.toastMessage = "Failed_to_create_group_call_error"
ToastViewModel.shared.displayToast = true
}
})
conferenceScheduler.addDelegate(delegate: self.conferenceSchedulerDelegate!)
}
func getContentTextMessage() {
let lastMessage = self.chatRoom.lastMessageInHistory
if lastMessage != nil {

View file

@ -70,4 +70,34 @@ class LinphoneUtils: NSObject {
core.defaultAccount?.params?.limeServerUrl != nil &&
core.defaultAccount?.params?.conferenceFactoryUri != nil
}
public class func createGroupCall(core: Core, account: Account?, subject: String) -> Conference? {
do {
let conferenceParams = try core.createConferenceParams(conference: nil)
conferenceParams.videoEnabled = true
conferenceParams.account = account
conferenceParams.subject = subject
// Enable end-to-end encryption if client supports it
if isEndToEndEncryptedChatAvailable(core: core) {
Log.info("\(#function) Requesting EndToEnd security level for conference")
conferenceParams.securityLevel = .EndToEnd
} else {
Log.info("\(#function) Requesting PointToPoint security level for conference")
conferenceParams.securityLevel = .PointToPoint
}
// Allows to have a chat room within the conference
conferenceParams.chatEnabled = true
Log.info("\(#function) Creating group call with subject \(conferenceParams.subject ?? "Unknown")")
let confWithParams = try core.createConferenceWithParams(params: conferenceParams)
return confWithParams
} catch let error {
Log.info("\(#function) Error while creating group call: \(error)")
return nil
}
}
}