From a0a1e1a417c40897d7f423ecdd385d4f0bacf3cf Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Fri, 14 Oct 2022 16:55:53 +0200 Subject: [PATCH 1/3] Bulk bug fixes conference --- .../Data/ScheduledConferenceData.swift | 9 ++++- .../Views/ScheduledConferencesCell.swift | 39 ++++++++++--------- .../Views/ScheduledConferencesView.swift | 7 +--- Classes/Swift/Voip/VoipDialog.swift | 4 +- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/Classes/Swift/Conference/Data/ScheduledConferenceData.swift b/Classes/Swift/Conference/Data/ScheduledConferenceData.swift index 2e351a8c0..c72646806 100644 --- a/Classes/Swift/Conference/Data/ScheduledConferenceData.swift +++ b/Classes/Swift/Conference/Data/ScheduledConferenceData.swift @@ -90,6 +90,10 @@ class ScheduledConferenceData { String(describing: participant.addressBookEnhancedDisplayName()) }.joined(separator: ", ") + if (participantsShort.value?.count == 0) { + participantsShort.value = " " + } + participantsExpanded.value = conferenceInfo.participants.map {(participant) in String(describing: participant.addressBookEnhancedDisplayName())+" ("+String(describing: participant.asStringUriOnly())+")" }.joined(separator: "\n") @@ -101,8 +105,9 @@ class ScheduledConferenceData { func deleteConference() { if (conferenceInfo.state != .Cancelled && canEdit.value == true) { Log.i("[Scheduled Conferences] Cancelling conference \(conferenceInfo.subject)") - ScheduledConferencesViewModel.shared.conferenceScheduler?.cancelConference(conferenceInfo: conferenceInfo) + try? Core.get().createConferenceScheduler().cancelConference(conferenceInfo: conferenceInfo) + } else { + Core.get().deleteConferenceInformation(conferenceInfo: conferenceInfo) } - Core.get().deleteConferenceInformation(conferenceInfo: conferenceInfo) } } diff --git a/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift b/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift index 408900867..a1ffe5e6d 100644 --- a/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift +++ b/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift @@ -50,6 +50,7 @@ class ScheduledConferencesCell: UITableViewCell { let joinEditDelete = UIStackView() let expandedRows = UIStackView() let selectionCheckBox = StyledCheckBox() + let myContentView = UIView() var conferenceData: ScheduledConferenceData? = nil { didSet { @@ -67,10 +68,10 @@ class ScheduledConferencesCell: UITableViewCell { self.urlValue.isHidden = data.isConferenceCancelled.value == true self.copyLink.isHidden = data.isConferenceCancelled.value == true data.expanded.readCurrentAndObserve { expanded in - self.contentView.backgroundColor = + self.myContentView.backgroundColor = data.conferenceInfo.state == .Cancelled ? VoipTheme.voip_conference_cancelled_bg_color : data.isFinished ? VoipTheme.backgroundColor3.get() : VoipTheme.backgroundColor4.get() - self.contentView.layer.borderWidth = expanded == true ? 2.0 : 0.0 + self.myContentView.layer.borderWidth = expanded == true ? 2.0 : 0.0 self.descriptionTitle.isHidden = expanded != true || self.descriptionValue.text?.count == 0 self.descriptionValue.isHidden = expanded != true || self.descriptionValue.text?.count == 0 self.infoConf.isSelected = expanded == true @@ -79,7 +80,7 @@ class ScheduledConferencesCell: UITableViewCell { self.expandedRows.isHidden = expanded != true self.joinEditDelete.isHidden = expanded != true if let myAddress = Core.get().defaultAccount?.params?.identityAddress { - self.editConf.isHidden = expanded != true || data.conferenceInfo.organizer?.weakEqual(address2: myAddress) != true + self.editConf.isHidden = expanded != true || data.conferenceInfo.organizer?.weakEqual(address2: myAddress) != true || data.conferenceInfo.state == .Cancelled } else { self.editConf.isHidden = true } @@ -99,31 +100,33 @@ class ScheduledConferencesCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - contentView.layer.cornerRadius = corner_radius - contentView.clipsToBounds = true - contentView.backgroundColor = VoipTheme.header_background_color - contentView.layer.borderColor = VoipTheme.primary_color.cgColor + contentView.addSubview(myContentView) + + myContentView.layer.cornerRadius = corner_radius + myContentView.clipsToBounds = true + myContentView.backgroundColor = VoipTheme.header_background_color + myContentView.layer.borderColor = VoipTheme.primary_color.cgColor + myContentView.matchParentDimmensions(insetedBy: UIEdgeInsets(top: 5,left: 0,bottom: 5,right: 0)).done() - - contentView.addSubview(clockIcon) + myContentView.addSubview(clockIcon) clockIcon.alignParentTop(withMargin: 15).square(15).alignParentLeft(withMargin: 10).done() - contentView.addSubview(timeDuration) + myContentView.addSubview(timeDuration) timeDuration.alignParentTop(withMargin: 15).toRightOf(clockIcon,withLeftMargin:10).alignHorizontalCenterWith(clockIcon).done() - contentView.addSubview(organiser) + myContentView.addSubview(organiser) organiser.alignParentTop(withMargin: 15).toRightOf(timeDuration, withLeftMargin:10).alignParentRight(withMargin:10).alignHorizontalCenterWith(clockIcon).done() let subjectCancel = UIStackView() subjectCancel.axis = .vertical - contentView.addSubview(subjectCancel) + myContentView.addSubview(subjectCancel) subjectCancel.alignUnder(view: timeDuration,withMargin: 15).alignParentLeft(withMargin: 10).done() subjectCancel.addArrangedSubview(cancelledLabel) subjectCancel.addArrangedSubview(subject) - contentView.addSubview(participantsIcon) + myContentView.addSubview(participantsIcon) participantsIcon.alignUnder(view: subject,withMargin: 15).square(15).alignParentLeft(withMargin: 10).done() //infoConf.onClick { @@ -131,18 +134,18 @@ class ScheduledConferencesCell: UITableViewCell { self.conferenceData?.toggleExpand() self.owningTableView?.reloadData() } - contentView.addSubview(infoConf) + myContentView.addSubview(infoConf) infoConf.imageView?.contentMode = .scaleAspectFit infoConf.alignUnder(view: subject,withMargin: 15).square(30).alignParentRight(withMargin: 10).alignHorizontalCenterWith(participantsIcon).done() infoConf.applyTintedIcons(tintedIcons: VoipTheme.conference_info_button) - contentView.addSubview(participants) + myContentView.addSubview(participants) participants.alignUnder(view: subject,withMargin: 15).toRightOf(participantsIcon,withLeftMargin:10).toRightOf(participantsIcon,withLeftMargin:10).toLeftOf(infoConf,withRightMargin: 15).done() expandedRows.axis = .vertical expandedRows.spacing = 10 - contentView.addSubview(expandedRows) + myContentView.addSubview(expandedRows) expandedRows.alignUnder(view: participants,withMargin: 15).matchParentSideBorders(insetedByDx:10).done() expandedRows.addArrangedSubview(descriptionTitle) @@ -166,7 +169,7 @@ class ScheduledConferencesCell: UITableViewCell { joinEditDelete.spacing = 10 joinEditDelete.distribution = .equalSpacing - contentView.addSubview(joinEditDelete) + myContentView.addSubview(joinEditDelete) joinEditDelete.alignUnder(view: expandedRows,withMargin: 15).alignParentRight(withMargin: 10).done() @@ -206,7 +209,7 @@ class ScheduledConferencesCell: UITableViewCell { deleteConf.onClick { self.askConfirmationTodeleteEntry() } - contentView.addSubview(selectionCheckBox) + myContentView.addSubview(selectionCheckBox) selectionCheckBox.alignParentRight(withMargin: delete_checkbox_margin).alignUnder(view:organiser, withMargin: delete_checkbox_margin).done() ScheduledConferencesViewModel.shared.editionEnabled.readCurrentAndObserve { editing in self.selectionCheckBox.isHidden = editing != true diff --git a/Classes/Swift/Conference/Views/ScheduledConferencesView.swift b/Classes/Swift/Conference/Views/ScheduledConferencesView.swift index 807cebf75..d7a3ec13b 100644 --- a/Classes/Swift/Conference/Views/ScheduledConferencesView.swift +++ b/Classes/Swift/Conference/Views/ScheduledConferencesView.swift @@ -182,12 +182,7 @@ import linphonesw } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let daysArray = Array(ScheduledConferencesViewModel.shared.daySplitted.keys.sorted().reversed()) - let day = daysArray[indexPath.section] - guard let data = ScheduledConferencesViewModel.shared.daySplitted[day]?[indexPath.row] else { - return UITableView.automaticDimension - } - return data.expanded.value! ? UITableView.automaticDimension : 100 + return UITableView.automaticDimension } diff --git a/Classes/Swift/Voip/VoipDialog.swift b/Classes/Swift/Voip/VoipDialog.swift index 84231fc65..c9d11f3eb 100644 --- a/Classes/Swift/Voip/VoipDialog.swift +++ b/Classes/Swift/Voip/VoipDialog.swift @@ -105,8 +105,10 @@ class VoipDialog : UIView{ toastQueue.append(message) return } + let rooVc = rootVC() let alert = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet) - rootVC()?.present(alert, animated: true) + alert.popoverPresentationController?.sourceView = PhoneMainView.instance().mainViewController.tabBarView + rooVc?.present(alert, animated: true) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + timeout) { alert.dismiss(animated: true) if (toastQueue.count > 0) { From b402f0800692e01f14f3363d42c12344448df146 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Wed, 19 Oct 2022 08:55:32 +0200 Subject: [PATCH 2/3] Send cancel conference iCS --- .../Data/ScheduledConferenceData.swift | 23 +++++++++++++++++-- .../ConferenceSchedulingViewModel.swift | 17 ++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Classes/Swift/Conference/Data/ScheduledConferenceData.swift b/Classes/Swift/Conference/Data/ScheduledConferenceData.swift index c72646806..86934f720 100644 --- a/Classes/Swift/Conference/Data/ScheduledConferenceData.swift +++ b/Classes/Swift/Conference/Data/ScheduledConferenceData.swift @@ -40,7 +40,8 @@ class ScheduledConferenceData { let canEdit = MutableLiveData(false) let isFinished : Bool let selectedForDeletion = MutableLiveData(false) - + private var conferenceSchedulerDelegate : ConferenceSchedulerDelegateStub? = nil + private var conferenceScheduler : ConferenceScheduler? = nil init (conferenceInfo: ConferenceInfo, isFinished: Bool = false) { self.conferenceInfo = conferenceInfo @@ -102,10 +103,28 @@ class ScheduledConferenceData { func gotoAssociatedChat() { } + + + func deleteConference() { + conferenceSchedulerDelegate = ConferenceSchedulerDelegateStub( + onStateChanged: { scheduler, state in + Log.i("[Conference Deletion] Conference scheduler state is \(state)") + if (state == .Ready) { + if let chatRoomParams = ConferenceSchedulingViewModel.shared.getConferenceInvitationsChatRoomParams() { + scheduler.sendInvitations(chatRoomParams: chatRoomParams) // Send cancel ICS + Log.e("[Conference Deletion] sent cancel ICS.") + } + } + }) + if (conferenceInfo.state != .Cancelled && canEdit.value == true) { Log.i("[Scheduled Conferences] Cancelling conference \(conferenceInfo.subject)") - try? Core.get().createConferenceScheduler().cancelConference(conferenceInfo: conferenceInfo) + self.conferenceScheduler = try? Core.get().createConferenceScheduler() + if (self.conferenceScheduler != nil) { + self.conferenceScheduler?.addDelegate(delegate: conferenceSchedulerDelegate!) + self.conferenceScheduler?.cancelConference(conferenceInfo: conferenceInfo) + } } else { Core.get().deleteConferenceInformation(conferenceInfo: conferenceInfo) } diff --git a/Classes/Swift/Conference/ViewModels/ConferenceSchedulingViewModel.swift b/Classes/Swift/Conference/ViewModels/ConferenceSchedulingViewModel.swift index cd5004231..bb4689e72 100644 --- a/Classes/Swift/Conference/ViewModels/ConferenceSchedulingViewModel.swift +++ b/Classes/Swift/Conference/ViewModels/ConferenceSchedulingViewModel.swift @@ -82,11 +82,7 @@ class ConferenceSchedulingViewModel { if (self.scheduleForLater.value == true && self.sendInviteViaChat.value == true) { // Send conference info even when conf is not scheduled for later // as the conference server doesn't invite participants automatically - if let chatRoomParams = try?self.core.createDefaultChatRoomParams() { - chatRoomParams.encryptionEnabled = self.isEndToEndEncryptedChatAvailable() - chatRoomParams.groupEnabled = false - chatRoomParams.backend = chatRoomParams.encryptionEnabled ? .FlexisipChat : .Basic - chatRoomParams.subject = self.subject.value! + if let chatRoomParams = self.getConferenceInvitationsChatRoomParams() { scheduler.sendInvitations(chatRoomParams: chatRoomParams) } } else { @@ -245,5 +241,16 @@ class ConferenceSchedulingViewModel { return [Duration(value: 30, display: "30min"), Duration(value: 60, display: "1h"), Duration(value: 120, display: "2h")] } + func getConferenceInvitationsChatRoomParams() -> ChatRoomParams? { + if let chatRoomParams = try?self.core.createDefaultChatRoomParams() { + chatRoomParams.encryptionEnabled = self.isEndToEndEncryptedChatAvailable() + chatRoomParams.groupEnabled = false + chatRoomParams.backend = chatRoomParams.encryptionEnabled ? .FlexisipChat : .Basic + chatRoomParams.subject = self.subject.value! + return chatRoomParams + } + return nil + } + } From 0353180bd0eacf58a6ac418632d5d77d51731d78 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Wed, 19 Oct 2022 09:53:01 +0200 Subject: [PATCH 3/3] Conference creation on iPad --- Classes/ChatConversationCreateView.h | 3 +++ Classes/ChatConversationCreateView.m | 13 ++++++++++++- Classes/ChatConversationInfoView.m | 2 ++ Classes/ChatsListTableView.m | 1 + Classes/ChatsListView.m | 1 + Classes/LinphoneAppDelegate.m | 1 + .../Views/ConferenceSchedulingSummaryView.swift | 1 + .../Conference/Views/ConferenceSchedulingView.swift | 3 ++- .../ParticipantsList/ParticipantsListView.swift | 3 ++- 9 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Classes/ChatConversationCreateView.h b/Classes/ChatConversationCreateView.h index 099090435..32e998c23 100644 --- a/Classes/ChatConversationCreateView.h +++ b/Classes/ChatConversationCreateView.h @@ -55,6 +55,9 @@ - (IBAction)onNextClick:(id)sender; - (IBAction)onChiffreClick:(id)sender; +-(void) unfragmentCompositeDescription; +-(void) fragmentCompositeDescription; + @end #endif /* ChatConversationCreateView_h */ diff --git a/Classes/ChatConversationCreateView.m b/Classes/ChatConversationCreateView.m index 12595171a..eb1074c94 100644 --- a/Classes/ChatConversationCreateView.m +++ b/Classes/ChatConversationCreateView.m @@ -45,6 +45,17 @@ static UICompositeViewDescription *compositeDescription = nil; return self.class.compositeViewDescription; } +-(void) unfragmentCompositeDescription { + compositeDescription.isLeftFragment = true; + compositeDescription.otherFragment = nil; +} + +-(void) fragmentCompositeDescription { + compositeDescription.otherFragment = IPAD ? NSStringFromClass(ChatsListView.class) : nil; + compositeDescription.isLeftFragment = false; +} + + - (void)viewDidLoad { [super viewDidLoad]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] @@ -131,7 +142,7 @@ static UICompositeViewDescription *compositeDescription = nil; } _waitView.hidden = YES; - _backButton.hidden = IPAD; + _backButton.hidden = IPAD && !(_isForVoipConference||_isForOngoingVoipConference); if(_tableController.contactsGroup.count == 0) { if (!_isForEditing) _nextButton.enabled = FALSE; diff --git a/Classes/ChatConversationInfoView.m b/Classes/ChatConversationInfoView.m index 3fc5da3db..a4ac1c6b7 100644 --- a/Classes/ChatConversationInfoView.m +++ b/Classes/ChatConversationInfoView.m @@ -270,6 +270,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (IBAction)onBackClick:(id)sender { if(_create) { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); + [view fragmentCompositeDescription]; view.tableController.contactsGroup = [_contacts mutableCopy]; view.tableController.notFirstTime = TRUE; view.isForEditing = FALSE; @@ -296,6 +297,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (IBAction)onAddClick:(id)sender { if (_create || _imAdmin) { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); + [view fragmentCompositeDescription]; view.tableController.notFirstTime = TRUE; view.isForEditing = !_create; view.isGroupChat = TRUE; diff --git a/Classes/ChatsListTableView.m b/Classes/ChatsListTableView.m index dfc9152fe..581f66c82 100644 --- a/Classes/ChatsListTableView.m +++ b/Classes/ChatsListTableView.m @@ -125,6 +125,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo [LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"create_chat"]; } else if (![self selectFirstRow]) { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); + [view fragmentCompositeDescription]; view.tableController.notFirstTime = FALSE; view.isForVoipConference = FALSE; [PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; diff --git a/Classes/ChatsListView.m b/Classes/ChatsListView.m index d689ec9cc..142618c35 100644 --- a/Classes/ChatsListView.m +++ b/Classes/ChatsListView.m @@ -117,6 +117,7 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)newChatCreate:(BOOL)isGroup { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); + [view fragmentCompositeDescription]; view.isForEditing = false; view.isGroupChat = isGroup; view.tableController.notFirstTime = FALSE; diff --git a/Classes/LinphoneAppDelegate.m b/Classes/LinphoneAppDelegate.m index 4d904dfa5..197720713 100644 --- a/Classes/LinphoneAppDelegate.m +++ b/Classes/LinphoneAppDelegate.m @@ -352,6 +352,7 @@ - (BOOL)handleShortcut:(UIApplicationShortcutItem *)shortcutItem { BOOL success = NO; if ([shortcutItem.type isEqualToString:@"linphone.phone.action.newMessage"]) { + [VIEW(ChatConversationCreateView) fragmentCompositeDescription]; [PhoneMainView.instance changeCurrentView:ChatConversationCreateView.compositeViewDescription]; success = YES; } diff --git a/Classes/Swift/Conference/Views/ConferenceSchedulingSummaryView.swift b/Classes/Swift/Conference/Views/ConferenceSchedulingSummaryView.swift index 9486d99dd..f8fbe6674 100644 --- a/Classes/Swift/Conference/Views/ConferenceSchedulingSummaryView.swift +++ b/Classes/Swift/Conference/Views/ConferenceSchedulingSummaryView.swift @@ -238,6 +238,7 @@ import SVProgressHUD func goBackParticipantsListSelection() { let view: ChatConversationCreateView = VIEW(ChatConversationCreateView.compositeViewDescription()) + view.unfragmentCompositeDescription() let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) } view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray view.tableController.notFirstTime = true diff --git a/Classes/Swift/Conference/Views/ConferenceSchedulingView.swift b/Classes/Swift/Conference/Views/ConferenceSchedulingView.swift index 24bac4748..ae2bd1da0 100644 --- a/Classes/Swift/Conference/Views/ConferenceSchedulingView.swift +++ b/Classes/Swift/Conference/Views/ConferenceSchedulingView.swift @@ -225,7 +225,8 @@ import IQKeyboardManager func gotoParticipantsListSelection() { - let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription()); + let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription()) + view.unfragmentCompositeDescription() let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) } view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray view.isForEditing = false diff --git a/Classes/Swift/Voip/Views/Fragments/ParticipantsList/ParticipantsListView.swift b/Classes/Swift/Voip/Views/Fragments/ParticipantsList/ParticipantsListView.swift index 2fc971b89..59f60e183 100644 --- a/Classes/Swift/Voip/Views/Fragments/ParticipantsList/ParticipantsListView.swift +++ b/Classes/Swift/Voip/Views/Fragments/ParticipantsList/ParticipantsListView.swift @@ -103,7 +103,8 @@ import linphonesw } func gotoParticipantsListSelection() { - let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription()); + let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription()) + view.unfragmentCompositeDescription() let addresses = ConferenceViewModel.shared.conferenceParticipants.value!.map { (data) in String(data.participant.address!.asStringUriOnly()) } view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray view.isForEditing = false