forked from mirrors/linphone-iphone
- Updated scheduling/group call tunnel
- Synchronized ConferenceViewModel with Android
This commit is contained in:
parent
1a9c6060c2
commit
8c66c4f96a
6 changed files with 88 additions and 66 deletions
|
|
@ -167,6 +167,9 @@ class ConferenceSchedulingViewModel {
|
|||
}.first
|
||||
|
||||
continueEnabled.value = false
|
||||
|
||||
selectedAddresses.value = []
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -190,23 +193,11 @@ class ConferenceSchedulingViewModel {
|
|||
|
||||
do {
|
||||
conferenceCreationInProgress.value = true
|
||||
guard let localAddress = core.defaultAccount?.params?.identityAddress else {
|
||||
guard let localAccount = core.defaultAccount, let localAddress = localAccount.params?.identityAddress else {
|
||||
Log.e("[Conference Creation] Couldn't get local address from default account!")
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Temporary workaround for chat room, to be removed once we can get matching chat room from conference
|
||||
let chatRoomParams = try core.createDefaultChatRoomParams()
|
||||
chatRoomParams.backend = ChatRoomBackend.FlexisipChat
|
||||
chatRoomParams.groupEnabled = true
|
||||
chatRoomParams.subject = subject.value!
|
||||
let chatRoom = try core.createChatRoom(params: chatRoomParams, localAddr: localAddress, participants: selectedAddresses.value!)
|
||||
Log.i("[Conference Creation] Creating chat room with same subject [\(subject.value)] & participants as for conference")
|
||||
chatRoom.addDelegate(delegate: chatRooomDelegate!)
|
||||
// END OF TODO
|
||||
*/
|
||||
|
||||
|
||||
let conferenceInfo = try Factory.Instance.createConferenceInfo()
|
||||
conferenceInfo.organizer = localAddress
|
||||
subject.value.map { conferenceInfo.subject = $0}
|
||||
|
|
@ -217,6 +208,7 @@ class ConferenceSchedulingViewModel {
|
|||
conferenceInfo.dateTime = time_t(timestamp)
|
||||
scheduledDuration.value.map { conferenceInfo.duration = UInt(ConferenceSchedulingViewModel.durationList[$0].value) }
|
||||
}
|
||||
conferenceScheduler?.account = localAccount
|
||||
conferenceScheduler?.info = conferenceInfo // Will trigger the conference creation automatically
|
||||
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ import SVProgressHUD
|
|||
contentView.addSubview(viaChatLabel)
|
||||
viaChatLabel.matchParentSideBorders(insetedByDx: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).done()
|
||||
ConferenceSchedulingViewModel.shared.sendInviteViaChat.readCurrentAndObserve { (sendChat) in
|
||||
viaChatLabel.isHidden = sendChat != true
|
||||
viaChatLabel.isHidden = sendChat != true || ConferenceSchedulingViewModel.shared.scheduleForLater.value != true
|
||||
}
|
||||
|
||||
// Participants
|
||||
|
|
@ -173,8 +173,8 @@ import SVProgressHUD
|
|||
let createButton = FormButton(backgroundStateColors: VoipTheme.primary_colors_background)
|
||||
contentView.addSubview(createButton)
|
||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { _ in
|
||||
createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule.uppercased() : VoipTexts.conference_schedule_create.uppercased()
|
||||
createButton.addSidePadding()
|
||||
createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
||||
createButton.addSidePadding()
|
||||
}
|
||||
|
||||
ConferenceSchedulingViewModel.shared.conferenceCreationInProgress.observe { progress in
|
||||
|
|
@ -211,8 +211,9 @@ import SVProgressHUD
|
|||
}
|
||||
}
|
||||
}
|
||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { _ in
|
||||
createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule.uppercased() : VoipTexts.conference_schedule_create.uppercased()
|
||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (later) in
|
||||
createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
||||
viaChatLabel.isHidden = later != true || ConferenceSchedulingViewModel.shared.sendInviteViaChat.value != true
|
||||
createButton.addSidePadding()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import linphonesw
|
|||
self.gotoParticipantsListSelection()
|
||||
},
|
||||
nextActionEnableCondition: ConferenceSchedulingViewModel.shared.continueEnabled,
|
||||
title:VoipTexts.conference_schedule_title)
|
||||
title:VoipTexts.conference_group_call_title)
|
||||
|
||||
let subjectLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_subject_title)
|
||||
subjectLabel.addIndicatorIcon(iconName: "voip_mandatory")
|
||||
|
|
@ -78,7 +78,6 @@ import linphonesw
|
|||
let scheduleForm = UIView()
|
||||
schedulingStack.addArrangedSubview(scheduleForm)
|
||||
scheduleForm.matchParentSideBorders().done()
|
||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in scheduleForm.isHidden = forLater != true }
|
||||
|
||||
// Left column (Date & Time)
|
||||
let leftColumn = UIView()
|
||||
|
|
@ -146,6 +145,8 @@ import linphonesw
|
|||
contentView.addSubview(viaChatLabel)
|
||||
viaChatLabel.toRightOf(viaChatSwitch,withLeftMargin: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).alignHorizontalCenterWith(viaChatSwitch).done()
|
||||
|
||||
/* Hidden as in Android 9.6.2022
|
||||
|
||||
let viaMailSwitch = StyledCheckBox(liveValue: ConferenceSchedulingViewModel.shared.sendInviteViaEmail)
|
||||
contentView.addSubview(viaMailSwitch)
|
||||
viaMailSwitch.alignParentLeft(withMargin: form_margin).alignUnder(view: viaChatSwitch,withMargin: 2*form_margin).done()
|
||||
|
|
@ -153,7 +154,6 @@ import linphonesw
|
|||
let viaMailLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_send_invite_email)
|
||||
contentView.addSubview(viaMailLabel)
|
||||
viaMailLabel.toRightOf(viaMailSwitch,withLeftMargin: form_margin).alignUnder(view: viaChatLabel,withMargin: 2*form_margin).alignHorizontalCenterWith(viaMailSwitch).done()
|
||||
|
||||
|
||||
// Encryption
|
||||
let encryptLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_encryption)
|
||||
|
|
@ -175,17 +175,27 @@ import linphonesw
|
|||
let encryptedIcon = UIImageView(image: UIImage(named: "security_toggle_icon_green"))
|
||||
encryptedIcon.contentMode = .scaleAspectFit
|
||||
encryptCombo.addArrangedSubview(encryptedIcon)
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// Mandatory label
|
||||
|
||||
let mandatoryLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_mandatory_field)
|
||||
mandatoryLabel.addIndicatorIcon(iconName: "voip_mandatory", trailing: false)
|
||||
contentView.addSubview(mandatoryLabel)
|
||||
mandatoryLabel.alignUnder(view: encryptCombo,withMargin: 4*form_margin).centerX().matchParentSideBorders().done()
|
||||
mandatoryLabel.alignUnder(view: viaChatSwitch,withMargin: 2*form_margin).centerX().matchParentSideBorders().done()
|
||||
mandatoryLabel.textAlignment = .center
|
||||
|
||||
mandatoryLabel.alignParentBottom().done()
|
||||
|
||||
// Schedule for later observer
|
||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in
|
||||
scheduleForm.isHidden = forLater != true
|
||||
super.titleLabel.text = forLater == true ? VoipTexts.conference_schedule_title : VoipTexts.conference_group_call_title
|
||||
viaChatSwitch.isHidden = forLater != true
|
||||
viaChatLabel.isHidden = forLater != true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ import UIKit
|
|||
static let call_remotely_paused_title = NSLocalizedString("Call has been paused by remote.",comment:"")
|
||||
|
||||
// Conference
|
||||
static let conference_schedule_title = NSLocalizedString("Start a conference",comment:"")
|
||||
static let conference_schedule_title = NSLocalizedString("Schedule a meeting",comment:"")
|
||||
static let conference_group_call_title = NSLocalizedString("Start a group call",comment:"")
|
||||
static let conference_schedule_later = NSLocalizedString("Do you want to schedule this conference for later?",comment:"")
|
||||
static let conference_schedule_mandatory_field = NSLocalizedString("Mandatory",comment:"")
|
||||
static let conference_schedule_subject_title = NSLocalizedString("Subject",comment:"")
|
||||
|
|
@ -77,15 +78,17 @@ import UIKit
|
|||
static let conference_schedule_send_invite_chat_summary = NSLocalizedString("Invite will be sent out from my \(appName) account",comment:"")
|
||||
static let conference_schedule_participants_list = NSLocalizedString("Participants list",comment:"")
|
||||
static let conference_schedule_summary = NSLocalizedString("Conference info",comment:"")
|
||||
static let conference_schedule_create = NSLocalizedString("Create conference",comment:"")
|
||||
static let conference_schedule_start = NSLocalizedString("Schedule meeting",comment:"")
|
||||
static let conference_group_call_create = NSLocalizedString("Start group call",comment:"")
|
||||
|
||||
static let conference_schedule = NSLocalizedString("Schedule conference",comment:"")
|
||||
static let conference_schedule_address_copied_to_clipboard = NSLocalizedString("Conference address copied into clipboard",comment:"")
|
||||
static let conference_schedule_creation_failure = NSLocalizedString("Failed to create conference!",comment:"")
|
||||
static let conference_schedule_info_not_sent_to_participant = NSLocalizedString("Failed to send conference info to a participant",comment:"")
|
||||
static let conference_paused_title = NSLocalizedString("You are currently out of the conference.",comment:"")
|
||||
static let conference_paused_subtitle = NSLocalizedString("Click on play button to join it back.",comment:"")
|
||||
static let conference_default_title = NSLocalizedString("Remote conference",comment:"")
|
||||
static let conference_local_title = NSLocalizedString("Local conference",comment:"")
|
||||
static let conference_default_title = NSLocalizedString("Remote group call",comment:"")
|
||||
static let conference_local_title = NSLocalizedString("Local group call",comment:"")
|
||||
static let conference_invite_title = NSLocalizedString("Conference invite:",comment:"")
|
||||
static let conference_description_title = NSLocalizedString("Description:",comment:"")
|
||||
static let conference_invite_join = NSLocalizedString("Join",comment:"")
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class CallData {
|
|||
let conference = call.conference
|
||||
isInRemoteConference.value = conference != nil || isCallingAConference()
|
||||
if (conference != nil) {
|
||||
remoteConferenceSubject.value = conference?.subject != nil && (conference?.subject.count)! > 0 ? conference!.subject : VoipTexts.conference_default_title
|
||||
remoteConferenceSubject.value = ConferenceViewModel.getConferenceSubject(conference: conference!)
|
||||
}
|
||||
isOutgoing.value = isOutGoing()
|
||||
isIncoming.value = isInComing()
|
||||
|
|
|
|||
|
|
@ -37,17 +37,21 @@ class ConferenceViewModel {
|
|||
let conferenceCreationPending = MutableLiveData<Bool>()
|
||||
let conferenceParticipants = MutableLiveData<[ConferenceParticipantData]>()
|
||||
let conferenceParticipantDevices = MutableLiveData<[ConferenceParticipantDeviceData]>()
|
||||
let conferenceDisplayMode = MutableLiveData<ConferenceLayout>()
|
||||
let conferenceDisplayMode = MutableLiveData<ConferenceDisplayMode>()
|
||||
|
||||
let isRecording = MutableLiveData<Bool>()
|
||||
let isRemotelyRecorded = MutableLiveData<Bool>()
|
||||
|
||||
let participantAdminStatusChangedEvent = MutableLiveData<ConferenceParticipantData>()
|
||||
|
||||
let maxParticipantsForMosaicLayout = ConfigManager.instance().lpConfigIntForKey(key: "max_conf_part_mosaic_layout",defaultValue: 6)
|
||||
|
||||
let speakingParticipant = MutableLiveData<ConferenceParticipantDeviceData>()
|
||||
|
||||
let participantAdminStatusChangedEvent = MutableLiveData<ConferenceParticipantData>()
|
||||
|
||||
let firstToJoinEvent = MutableLiveData<Bool>()
|
||||
|
||||
let allParticipantsLeftEvent = MutableLiveData<Bool>()
|
||||
|
||||
private var conferenceDelegate : ConferenceDelegateStub?
|
||||
private var coreDelegate : CoreDelegateStub?
|
||||
|
||||
|
|
@ -66,6 +70,9 @@ class ConferenceViewModel {
|
|||
onParticipantRemoved: {(conference: Conference, participant: Participant) in
|
||||
Log.i("[Conference] \(conference) \(participant) Participant removed")
|
||||
self.updateParticipantsList(conference)
|
||||
if (self.conferenceParticipants.value?.count == 0) {
|
||||
self.allParticipantsLeftEvent.value = true
|
||||
}
|
||||
},
|
||||
onParticipantDeviceAdded: {(conference: Conference, participantDevice: ParticipantDevice) in
|
||||
Log.i("[Conference] \(conference) Participant device \(participantDevice) added")
|
||||
|
|
@ -100,7 +107,7 @@ class ConferenceViewModel {
|
|||
},
|
||||
onStateChanged: { (conference: Conference, state: Conference.State) in
|
||||
Log.i("[Conference] State changed: \(state)")
|
||||
self.isVideoConference.value = conference.currentParams?.isVideoEnabled
|
||||
self.isVideoConference.value = conference.currentParams?.videoEnabled
|
||||
if (state == .Created) {
|
||||
self.configureConference(conference)
|
||||
self.conferenceCreationPending.value = false
|
||||
|
|
@ -141,8 +148,6 @@ class ConferenceViewModel {
|
|||
Core.get().addDelegate(delegate: coreDelegate!)
|
||||
conferenceParticipants.value = []
|
||||
conferenceParticipantDevices.value = []
|
||||
conferenceDisplayMode.value = .Grid
|
||||
subject.value = VoipTexts.conference_default_title
|
||||
|
||||
if let conference = core.conference != nil ? core.conference : core.currentCall?.conference {
|
||||
Log.i("[Conference] Found an existing conference: \(conference) in state \(conference.state)")
|
||||
|
|
@ -182,42 +187,30 @@ class ConferenceViewModel {
|
|||
|
||||
func initConference(_ conference: Conference) {
|
||||
conferenceExists.value = true
|
||||
|
||||
self.conference.value = conference
|
||||
conference.addDelegate(delegate: self.conferenceDelegate!)
|
||||
|
||||
isRecording.value = conference.isRecording
|
||||
subject.value = ConferenceViewModel.getConferenceSubject(conference: conference)
|
||||
|
||||
updateConferenceLayout(conference: conference)
|
||||
|
||||
if let call = core.currentCall, CallManager.getAppData(call: call.getCobject!)?.isConference == true { // Apply waiting room preference
|
||||
if (ConferenceWaitingRoomViewModel.sharedModel.isSpeakerSelected.value == true) {
|
||||
ControlsViewModel.shared.forceSpeakerAudioRoute()
|
||||
} else {
|
||||
ControlsViewModel.shared.forceEarpieceAudioRoute()
|
||||
ControlsViewModel.shared.updateUI()
|
||||
}
|
||||
Core.get().micEnabled = ConferenceWaitingRoomViewModel.sharedModel.isMicrophoneMuted.value != true
|
||||
changeLayout(layout: ConferenceWaitingRoomViewModel.sharedModel.joinLayout.value!)
|
||||
updateConferenceLayout(conference: conference)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func configureConference(_ conference: Conference) {
|
||||
self.updateParticipantsList(conference)
|
||||
if (conferenceParticipants.value?.count == 0) {
|
||||
firstToJoinEvent.value = true
|
||||
}
|
||||
self.updateParticipantsDevicesList(conference)
|
||||
|
||||
isConferenceLocallyPaused.value = !conference.isIn
|
||||
self.isMeAdmin.value = conference.me?.isAdmin == true
|
||||
isVideoConference.value = conference.currentParams?.videoEnabled == true
|
||||
|
||||
self.subject.value = conference.subject.isEmpty ? (
|
||||
conference.me?.isFocus == true ? (
|
||||
VoipTexts.conference_local_title
|
||||
) : (
|
||||
VoipTexts.conference_default_title
|
||||
)
|
||||
) : (
|
||||
conference.subject
|
||||
)
|
||||
subject.value = ConferenceViewModel.getConferenceSubject(conference: conference)
|
||||
updateConferenceLayout(conference: conference)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -238,12 +231,13 @@ class ConferenceViewModel {
|
|||
}
|
||||
|
||||
|
||||
func changeLayout(layout: ConferenceLayout) {
|
||||
func changeLayout(layout: ConferenceDisplayMode) {
|
||||
Log.i("[Conference] Trying to change conference layout to $layout")
|
||||
if let conference = conference.value, let call = conference.call, let params = try?call.core?.createCallParams(call: call) {
|
||||
params.videoEnabled = true // TODO AUdioLonly layout != ConferenceDisplayMode.AUDIO_ONLY
|
||||
params.conferenceVideoLayout = layout
|
||||
params.videoEnabled = layout != .AudioOnly
|
||||
params.conferenceVideoLayout = layout == ConferenceDisplayMode.Grid ? .Grid : .ActiveSpeaker
|
||||
try?call.update(params: params)
|
||||
|
||||
conferenceDisplayMode.value = layout
|
||||
let list = sortDevicesDataList(devices: conferenceParticipantDevices.value!)
|
||||
conferenceParticipantDevices.value = list
|
||||
|
|
@ -254,7 +248,7 @@ class ConferenceViewModel {
|
|||
|
||||
private func updateConferenceLayout(conference: Conference) {
|
||||
if let call = conference.call, let params = call.params {
|
||||
conferenceDisplayMode.value = params.conferenceVideoLayout
|
||||
conferenceDisplayMode.value = !params.videoEnabled ? ConferenceDisplayMode.AudioOnly : params.conferenceVideoLayout == .Grid ? .Grid : .ActiveSpeaker
|
||||
let list = sortDevicesDataList(devices: conferenceParticipantDevices.value!)
|
||||
conferenceParticipantDevices.value = list
|
||||
Log.i("[Conference] Conference current layout is: \(conferenceDisplayMode.value)")
|
||||
|
|
@ -275,7 +269,7 @@ class ConferenceViewModel {
|
|||
conferenceParticipantDevices.value = []
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func updateParticipantsList(_ conference: Conference) {
|
||||
self.conferenceParticipants.value?.forEach{ $0.destroy()}
|
||||
var participants :[ConferenceParticipantData] = []
|
||||
|
|
@ -370,7 +364,7 @@ class ConferenceViewModel {
|
|||
return devices
|
||||
}
|
||||
|
||||
|
||||
|
||||
func togglePlayPause () {
|
||||
if (isConferenceLocallyPaused.value == true) {
|
||||
resumeConference()
|
||||
|
|
@ -412,6 +406,25 @@ class ConferenceViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
static func getConferenceSubject(conference:Conference) -> String? {
|
||||
if (conference.subject.count > 0) {
|
||||
return conference.subject
|
||||
} else {
|
||||
let conferenceInfo = Core.get().findConferenceInformationFromUri(uri: conference.conferenceAddress!)
|
||||
if (conferenceInfo != nil) {
|
||||
return conferenceInfo?.subject
|
||||
} else {
|
||||
if (conference.me?.isFocus == true) {
|
||||
return VoipTexts.conference_local_title
|
||||
} else {
|
||||
return VoipTexts.conference_default_title
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@objc class ConferenceViewModelBridge : NSObject {
|
||||
|
|
@ -425,12 +438,15 @@ class ConferenceViewModel {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
enum FlexDirection {
|
||||
case ROW
|
||||
case ROW_REVERSE
|
||||
case COLUMN
|
||||
case COLUMN_REVERSE
|
||||
}
|
||||
|
||||
enum ConferenceDisplayMode {
|
||||
case Grid
|
||||
case ActiveSpeaker
|
||||
case AudioOnly
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue