From 1e4d8f55a735e2ba56d494b27933c4ec06fd0e9b Mon Sep 17 00:00:00 2001 From: QuentinArguillere Date: Tue, 9 Apr 2024 12:12:08 +0200 Subject: [PATCH] Implement MeetingViewModel --- .../Meetings/ViewModel/MeetingViewModel.swift | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/Linphone/UI/Main/Meetings/ViewModel/MeetingViewModel.swift b/Linphone/UI/Main/Meetings/ViewModel/MeetingViewModel.swift index 9afe0ac22..d65261290 100644 --- a/Linphone/UI/Main/Meetings/ViewModel/MeetingViewModel.swift +++ b/Linphone/UI/Main/Meetings/ViewModel/MeetingViewModel.swift @@ -18,7 +18,186 @@ */ import Foundation +import linphonesw + +// TODO: à merger avec le ParticipantModel de la branche de Benoit +class ParticipantModel: ObservableObject { + + static let TAG = "[Participant Model]" + + let address: Address + @Published var sipUri: String + @Published var name: String + @Published var avatarModel: ContactAvatarModel + + init(address: Address) { + self.address = address + + self.sipUri = address.asStringUriOnly() + + let addressFriend = ContactsManager.shared.getFriendWithAddress(address: self.address) + + var nameTmp = "" + + if addressFriend != nil { + nameTmp = addressFriend!.name! + } else { + nameTmp = address.displayName != nil + ? address.displayName! + : address.username! + } + + self.name = nameTmp + + self.avatarModel = addressFriend != nil + ? ContactsManager.shared.avatarListModel.first(where: { + $0.friend!.name == addressFriend!.name + && $0.friend!.address!.asStringUriOnly() == address.asStringUriOnly() + }) ?? ContactAvatarModel(friend: nil, name: nameTmp, withPresence: false) + : ContactAvatarModel(friend: nil, name: nameTmp, withPresence: false) + } +} class MeetingViewModel: ObservableObject { + static let TAG = "[Meeting ViewModel]" + private var coreContext = CoreContext.shared + + @Published var showBackbutton: Bool = false + @Published var isBroadcast: Bool = false + @Published var isEditable: Bool = false + @Published var subject: String = "" + @Published var sipUri: String = "" + @Published var description: String? + @Published var timezone: String = "" + @Published var startDate: Date? + @Published var endDate: Date? + @Published var dateTime: String = "" + + @Published var speakers: [ParticipantModel] = [] + @Published var participants: [ParticipantModel] = [] + @Published var conferenceInfoFoundEvent: Bool = false + + var conferenceInfo: ConferenceInfo? + + init() { + + } + + func findConferenceInfo(uri: String) { + coreContext.doOnCoreQueue { core in + var confInfoFound = false + if let address = try? Factory.Instance.createAddress(addr: uri) { + let foundConfInfo = core.findConferenceInformationFromUri(uri: address) + if foundConfInfo != nil { + Log.info("\(MeetingViewModel.TAG) Conference info with SIP URI \(uri) was found") + self.conferenceInfo = foundConfInfo + self.configureConferenceInfo(core: core) + confInfoFound = true + } else { + Log.error("\(MeetingViewModel.TAG) Conference info with SIP URI \(uri) couldn't be found!") + confInfoFound = false + } + } else { + Log.error("\(MeetingViewModel.TAG) Failed to parse SIP URI \(uri) as Address!") + confInfoFound = false + } + DispatchQueue.main.sync { + self.conferenceInfoFoundEvent = confInfoFound + } + } + } + + private func configureConferenceInfo(core: Core) { + if let confInfo = self.conferenceInfo { + + /* + timezone.postValue( + AppUtils.getFormattedString( + R.string.meeting_schedule_timezone_title, + TimeZone.getDefault().displayName + ) + .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + ) + */ + + var isEditable = false + + if let organizerAddress = confInfo.organizer { + let localAccount = core.accountList.first(where: { + if let address = $0.params?.identityAddress { + return organizerAddress.weakEqual(address2: address) + } else { + return false + } + }) + + isEditable = localAccount != nil + } else { + Log.error("\(MeetingViewModel.TAG) No organizer SIP URI found for: \(confInfo.uri?.asStringUriOnly() ?? "(empty)")") + } + + let startDate = Date(timeIntervalSince1970: TimeInterval(confInfo.dateTime)) + let endDate = Calendar.current.date(byAdding: .minute, value: Int(confInfo.duration), to: startDate)! + + let formatter = DateFormatter() + formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a" + let startTime = formatter.string(from: startDate) + let endTime = formatter.string(from: endDate) + let dateTime = "\(startTime) - \(endTime)" + + DispatchQueue.main.sync { + self.subject = confInfo.subject ?? "" + self.sipUri = confInfo.uri?.asStringUriOnly() ?? "" + self.description = confInfo.description + self.startDate = startDate + self.endDate = endDate + self.dateTime = dateTime + self.isEditable = isEditable + } + + self.computeParticipantsList(core: core, confInfo: confInfo) + } + } + + private func computeParticipantsList(core: Core, confInfo: ConferenceInfo) { + var speakersList: [ParticipantModel] = [] + var participantsList: [ParticipantModel] = [] + var allSpeaker = true + let organizer = confInfo.organizer + var organizerFound = false + for pInfo in confInfo.participantInfos { + if let participantAddress = pInfo.address { + let isOrganizer = organizer != nil && organizer!.weakEqual(address2: participantAddress) + + Log.info("\(MeetingViewModel.TAG) Conference \(confInfo.subject)[${conferenceInfo.subject}] \(isOrganizer ? "organizer: " : "participant: ") \(participantAddress.asStringUriOnly()) is a \(pInfo.role)") + if isOrganizer { + organizerFound = true + } + + if pInfo.role == Participant.Role.Listener { + allSpeaker = false + participantsList.append(ParticipantModel(address: participantAddress)) + } else { + speakersList.append(ParticipantModel(address: participantAddress)) + } + } + } + + if allSpeaker { + Log.info("$TAG All participants have Speaker role, considering it is a meeting") + participantsList = speakersList + } + + if !organizerFound, let organizerAddress = organizer { + Log.info("$TAG Organizer not found in participants list, adding it to participants list") + participantsList.append(ParticipantModel(address: organizerAddress)) + } + + DispatchQueue.main.sync { + self.isBroadcast = !allSpeaker + speakers = speakersList + participants = participantsList + } + } }