diff --git a/Riot/Managers/Call/CallPresenter.swift b/Riot/Managers/Call/CallPresenter.swift index 91f738ff4..40e4f0fbb 100644 --- a/Riot/Managers/Call/CallPresenter.swift +++ b/Riot/Managers/Call/CallPresenter.swift @@ -43,14 +43,13 @@ class CallPresenter: NSObject { /// Call background tasks map. Keys are callIds. private var callBackgroundTasks: [String: MXBackgroundTask] = [:] /// Actively presented direct call view controller. - private weak var presentedCallVC: CallViewController? { + private weak var presentedCallVC: UIViewController? { didSet { updateOnHoldCall() } } private weak var inBarCallVC: UIViewController? - private weak var pipCallVC: CallViewController? - private weak var pipGroupCallVC: JitsiViewController? + private weak var pipCallVC: UIViewController? /// UI operation queue for various UI operations private var uiOperationQueue: OperationQueue = .main /// Flag to indicate whether the presenter is active. @@ -140,9 +139,9 @@ class CallPresenter: NSObject { } if let jitsiVC = jitsiVC { dismissCallBar(for: jitsiVC) - presentGroupCallVC(jitsiVC) + presentCallVC(jitsiVC) } - if let temporaryJitsiVC = temporaryJitsiVC, !uiOperationQueue.containsPresentGroupCallVCOperation { + if let temporaryJitsiVC = temporaryJitsiVC, !uiOperationQueue.containsPresentCallVCOperation { dismissCallBar(for: temporaryJitsiVC) displayJitsiCall(withWidget: temporaryJitsiVC.widget) } @@ -161,7 +160,7 @@ class CallPresenter: NSObject { guard let self = self else { return } if let jitsiVC = self.jitsiVC { jitsiVC.delegate = self - self.presentGroupCallVC(jitsiVC) + self.presentCallVC(jitsiVC) self.startJitsiCall(withWidget: widget) } }, failure: { [weak self] (error) in @@ -174,7 +173,7 @@ class CallPresenter: NSObject { if let jitsiVC = jitsiVC, jitsiVC.widget.widgetId == widget.widgetId { if jitsiVC.widget.widgetId == widget.widgetId { - self.presentGroupCallVC(jitsiVC) + self.presentCallVC(jitsiVC) } else { // end previous Jitsi call first endActiveJitsiCall() @@ -239,7 +238,7 @@ class CallPresenter: NSObject { } if let jitsiVC = jitsiVC { - dismissGroupCallVC(jitsiVC) + dismissCallVC(jitsiVC) jitsiVC.hangup() } @@ -322,7 +321,7 @@ class CallPresenter: NSObject { // MARK: - Private private func updateOnHoldCall() { - guard let presentedCallVC = presentedCallVC else { + guard let presentedCallVC = presentedCallVC as? CallViewController else { return } @@ -393,6 +392,14 @@ class CallPresenter: NSObject { } } + private func logCallVC(_ callVC: UIViewController, log: String) { + if let callVC = callVC as? CallViewController { + NSLog("[CallPresenter] \(log): call: \(String(describing: callVC.mxCall?.callId))") + } else if let callVC = callVC as? JitsiViewController { + NSLog("[CallPresenter] \(log): call: \(callVC.widget.widgetId)") + } + } + // MARK: - Timer private func startCallTimer() { @@ -657,7 +664,7 @@ class CallPresenter: NSObject { return } - presentGroupCallVC(jitsiVC) + presentCallVC(jitsiVC) } @objc @@ -685,7 +692,7 @@ class CallPresenter: NSObject { guard let self = self else { return } self.temporaryJitsiVC = newJitsiVC newJitsiVC.delegate = self - self.presentCallBar(for: newJitsiVC) + self.presentCallBar(for: newJitsiVC, isTemporary: true) } failure: { (error) in } @@ -719,8 +726,8 @@ class CallPresenter: NSObject { // MARK: - Call Screens - private func presentCallVC(_ callVC: CallViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] presentCallVC: call: \(String(describing: callVC.mxCall?.callId))") + private func presentCallVC(_ callVC: UIViewController, completion: (() -> Void)? = nil) { + logCallVC(callVC, log: "presentCallVC") // do not use PiP transitions here, as we really want to present the screen callVC.transitioningDelegate = nil @@ -743,8 +750,8 @@ class CallPresenter: NSObject { uiOperationQueue.addOperation(operation) } - private func dismissCallVC(_ callVC: CallViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] dismissCallVC: call: \(String(describing: callVC.mxCall?.callId))") + private func dismissCallVC(_ callVC: UIViewController, completion: (() -> Void)? = nil) { + logCallVC(callVC, log: "dismissCallVC") // do not use PiP transitions here, as we really want to dismiss the screen callVC.transitioningDelegate = nil @@ -758,8 +765,8 @@ class CallPresenter: NSObject { uiOperationQueue.addOperation(operation) } - private func enterPipCallVC(_ callVC: CallViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] enterPipCallVC: call: \(String(describing: callVC.mxCall?.callId))") + private func enterPipCallVC(_ callVC: UIViewController, completion: (() -> Void)? = nil) { + logCallVC(callVC, log: "enterPipCallVC") // assign self as transitioning delegate callVC.transitioningDelegate = self @@ -774,8 +781,8 @@ class CallPresenter: NSObject { uiOperationQueue.addOperation(operation) } - private func exitPipCallVC(_ callVC: CallViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] exitPipCallVC: call: \(String(describing: callVC.mxCall?.callId))") + private func exitPipCallVC(_ callVC: UIViewController, completion: (() -> Void)? = nil) { + logCallVC(callVC, log: "exitPipCallVC") // assign self as transitioning delegate callVC.transitioningDelegate = self @@ -792,19 +799,17 @@ class CallPresenter: NSObject { // MARK: - Call Bar - private func presentCallBar(for callVC: UIViewController?, completion: (() -> Void)? = nil) { - if let callVC = callVC as? CallViewController { - NSLog("[CallPresenter] presentCallBar: call: \(String(describing: callVC.mxCall?.callId))") - } else if let callVC = callVC as? JitsiViewController { - NSLog("[CallPresenter] presentCallBar: call: \(callVC.widget.widgetId)") - } + private func presentCallBar(for callVC: UIViewController, isTemporary: Bool = false, completion: (() -> Void)? = nil) { + logCallVC(callVC, log: "presentCallBar") let activeCallVC = self.activeCallVC let operation = CallBarPresentOperation(presenter: self, activeCallVC: activeCallVC, numberOfPausedCalls: numberOfPausedCalls) { [weak self] in - // active calls are more prior to paused ones. - // So, if user taps the bar when we have one active and one paused call, we navigate to the active one. - self?.inBarCallVC = activeCallVC ?? callVC + if !isTemporary { + // active calls are more prior to paused ones. + // So, if user taps the bar when we have one active and one paused call, we navigate to the active one. + self?.inBarCallVC = activeCallVC ?? callVC + } completion?() } uiOperationQueue.addOperation(operation) @@ -818,11 +823,7 @@ class CallPresenter: NSObject { } private func dismissCallBar(for callVC: UIViewController, completion: (() -> Void)? = nil) { - if let callVC = callVC as? CallViewController { - NSLog("[CallPresenter] dismissCallBar: call: \(String(describing: callVC.mxCall?.callId))") - } else if let callVC = callVC as? JitsiViewController { - NSLog("[CallPresenter] dismissCallBar: call: \(callVC.widget.widgetId)") - } + logCallVC(callVC, log: "dismissCallBar") let operation = CallBarDismissOperation(presenter: self) { [weak self] in if callVC == self?.inBarCallVC { @@ -834,42 +835,6 @@ class CallPresenter: NSObject { uiOperationQueue.addOperation(operation) } - // MARK - Group Calls - - private func presentGroupCallVC(_ callVC: JitsiViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] presentGroupCallVC: call: \(callVC.widget.widgetId)") - - // do not use PiP transitions here, as we really want to present the screen - callVC.transitioningDelegate = nil - - if let inBarCallVC = inBarCallVC { - dismissCallBar(for: inBarCallVC) - } - - if let presentedCallVC = presentedCallVC { - dismissCallVC(presentedCallVC) - } - - let operation = GroupCallVCPresentOperation(presenter: self, callVC: callVC) { [weak self] in - self?.jitsiVC = callVC - if callVC == self?.pipGroupCallVC { - self?.pipGroupCallVC = nil - } - completion?() - } - uiOperationQueue.addOperation(operation) - } - - private func dismissGroupCallVC(_ callVC: JitsiViewController, completion: (() -> Void)? = nil) { - NSLog("[CallPresenter] dismissGroupCallVC: call: \(callVC.widget.widgetId)") - - // do not use PiP transitions here, as we really want to dismiss the screen - callVC.transitioningDelegate = nil - - let operation = GroupCallVCDismissOperation(presenter: self, callVC: callVC, completion: completion) - uiOperationQueue.addOperation(operation) - } - } // MARK: - MXKCallViewControllerDelegate @@ -959,10 +924,6 @@ extension OperationQueue { return containsOperation(ofType: CallBarPresentOperation.self) } - var containsPresentGroupCallVCOperation: Bool { - return containsOperation(ofType: GroupCallVCPresentOperation.self) - } - private func containsOperation(ofType type: Operation.Type) -> Bool { return operations.contains { (operation) -> Bool in return operation.isKind(of: type.self) @@ -995,7 +956,7 @@ extension CallPresenter: JMCallKitListener { if let jitsiVC = jitsiVC, jitsiVC.widget.widgetId == widget.widgetId { // hangup an active call - dismissGroupCallVC(jitsiVC) + dismissCallVC(jitsiVC) endActiveJitsiCall() } else { // decline incoming call @@ -1044,8 +1005,7 @@ extension CallPresenter: JitsiViewControllerDelegate { func jitsiViewController(_ jitsiViewController: JitsiViewController!, goBackToApp completion: (() -> Void)!) { if jitsiViewController == jitsiVC || jitsiViewController == temporaryJitsiVC { - dismissGroupCallVC(jitsiViewController) - self.presentCallBar(for: jitsiViewController, completion: completion) + enterPipCallVC(jitsiViewController) } } diff --git a/Riot/Managers/Call/CallPresenterDelegate.swift b/Riot/Managers/Call/CallPresenterDelegate.swift index c94845891..57ee1c941 100644 --- a/Riot/Managers/Call/CallPresenterDelegate.swift +++ b/Riot/Managers/Call/CallPresenterDelegate.swift @@ -20,10 +20,10 @@ import Foundation protocol CallPresenterDelegate: class { // Call screens func callPresenter(_ presenter: CallPresenter, - presentCallViewController viewController: CallViewController, + presentCallViewController viewController: UIViewController, completion:(() -> Void)?) func callPresenter(_ presenter: CallPresenter, - dismissCallViewController viewController: CallViewController, + dismissCallViewController viewController: UIViewController, completion:(() -> Void)?) // Call Bar @@ -39,18 +39,10 @@ protocol CallPresenterDelegate: class { // PiP func callPresenter(_ presenter: CallPresenter, - enterPipForCallViewController viewController: CallViewController, + enterPipForCallViewController viewController: UIViewController, completion:(() -> Void)?) func callPresenter(_ presenter: CallPresenter, - exitPipForCallViewController viewController: CallViewController, - completion:(() -> Void)?) - - // Group Calls - func callPresenter(_ presenter: CallPresenter, - presentGroupCallViewController viewController: JitsiViewController, - completion:(() -> Void)?) - func callPresenter(_ presenter: CallPresenter, - dismissGroupCallViewController viewController: JitsiViewController, + exitPipForCallViewController viewController: UIViewController, completion:(() -> Void)?) } diff --git a/Riot/Managers/Call/Operations/CallVCDismissOperation.swift b/Riot/Managers/Call/Operations/CallVCDismissOperation.swift index 7a7073d39..facc8428c 100644 --- a/Riot/Managers/Call/Operations/CallVCDismissOperation.swift +++ b/Riot/Managers/Call/Operations/CallVCDismissOperation.swift @@ -19,11 +19,11 @@ import Foundation class CallVCDismissOperation: AsyncOperation { private var presenter: CallPresenter - private var callVC: CallViewController + private var callVC: UIViewController private var completion: (() -> Void)? init(presenter: CallPresenter, - callVC: CallViewController, + callVC: UIViewController, completion: (() -> Void)? = nil) { self.presenter = presenter self.callVC = callVC diff --git a/Riot/Managers/Call/Operations/CallVCEnterPipOperation.swift b/Riot/Managers/Call/Operations/CallVCEnterPipOperation.swift index be140e7ae..74bde2785 100644 --- a/Riot/Managers/Call/Operations/CallVCEnterPipOperation.swift +++ b/Riot/Managers/Call/Operations/CallVCEnterPipOperation.swift @@ -19,11 +19,11 @@ import Foundation class CallVCEnterPipOperation: AsyncOperation { private var presenter: CallPresenter - private var callVC: CallViewController + private var callVC: UIViewController private var completion: (() -> Void)? init(presenter: CallPresenter, - callVC: CallViewController, + callVC: UIViewController, completion: (() -> Void)? = nil) { self.presenter = presenter self.callVC = callVC diff --git a/Riot/Managers/Call/Operations/CallVCExitPipOperation.swift b/Riot/Managers/Call/Operations/CallVCExitPipOperation.swift index 0a4d17147..1e74c7ded 100644 --- a/Riot/Managers/Call/Operations/CallVCExitPipOperation.swift +++ b/Riot/Managers/Call/Operations/CallVCExitPipOperation.swift @@ -19,11 +19,11 @@ import Foundation class CallVCExitPipOperation: AsyncOperation { private var presenter: CallPresenter - private var callVC: CallViewController + private var callVC: UIViewController private var completion: (() -> Void)? init(presenter: CallPresenter, - callVC: CallViewController, + callVC: UIViewController, completion: (() -> Void)? = nil) { self.presenter = presenter self.callVC = callVC diff --git a/Riot/Managers/Call/Operations/CallVCPresentOperation.swift b/Riot/Managers/Call/Operations/CallVCPresentOperation.swift index 1a58f86cd..fae80e51b 100644 --- a/Riot/Managers/Call/Operations/CallVCPresentOperation.swift +++ b/Riot/Managers/Call/Operations/CallVCPresentOperation.swift @@ -19,11 +19,11 @@ import Foundation class CallVCPresentOperation: AsyncOperation { private var presenter: CallPresenter - private var callVC: CallViewController + private var callVC: UIViewController private var completion: (() -> Void)? init(presenter: CallPresenter, - callVC: CallViewController, + callVC: UIViewController, completion: (() -> Void)? = nil) { self.presenter = presenter self.callVC = callVC diff --git a/Riot/Managers/Call/Operations/GroupCallVCDismissOperation.swift b/Riot/Managers/Call/Operations/GroupCallVCDismissOperation.swift deleted file mode 100644 index a19402c3e..000000000 --- a/Riot/Managers/Call/Operations/GroupCallVCDismissOperation.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2020 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -class GroupCallVCDismissOperation: AsyncOperation { - - private var presenter: CallPresenter - private var callVC: JitsiViewController - private var completion: (() -> Void)? - - init(presenter: CallPresenter, - callVC: JitsiViewController, - completion: (() -> Void)? = nil) { - self.presenter = presenter - self.callVC = callVC - self.completion = completion - } - - override func main() { - presenter.delegate?.callPresenter(presenter, dismissGroupCallViewController: callVC, completion: { - self.finish() - self.completion?() - }) - } - -} diff --git a/Riot/Managers/Call/Operations/GroupCallVCPresentOperation.swift b/Riot/Managers/Call/Operations/GroupCallVCPresentOperation.swift deleted file mode 100644 index 2858cab0a..000000000 --- a/Riot/Managers/Call/Operations/GroupCallVCPresentOperation.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2020 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -class GroupCallVCPresentOperation: AsyncOperation { - - private var presenter: CallPresenter - private var callVC: JitsiViewController - private var completion: (() -> Void)? - - init(presenter: CallPresenter, - callVC: JitsiViewController, - completion: (() -> Void)? = nil) { - self.presenter = presenter - self.callVC = callVC - self.completion = completion - } - - override func main() { - presenter.delegate?.callPresenter(presenter, presentGroupCallViewController: callVC, completion: { - self.finish() - self.completion?() - }) - } - -} diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index e5cc5af4d..036fdc9bc 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -4378,16 +4378,20 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [self presentViewController:viewController animated:YES completion:completion]; } -- (void)callPresenter:(CallPresenter *)presenter dismissCallViewController:(CallViewController *)viewController completion:(void (^)(void))completion +- (void)callPresenter:(CallPresenter *)presenter dismissCallViewController:(UIViewController *)viewController completion:(void (^)(void))completion { // Check whether the call view controller is actually presented if (viewController.presentingViewController) { [viewController.presentingViewController dismissViewControllerAnimated:YES completion:^{ - if (viewController.shouldPromptForStunServerFallback) + if ([viewController isKindOfClass:CallViewController.class]) { - [self promptForStunServerFallback]; + CallViewController *callVC = (CallViewController *)viewController; + if (callVC.shouldPromptForStunServerFallback) + { + [self promptForStunServerFallback]; + } } if (completion) @@ -4497,7 +4501,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } } -- (void)callPresenter:(CallPresenter *)presenter enterPipForCallViewController:(CallViewController *)viewController completion:(void (^)(void))completion +- (void)callPresenter:(CallPresenter *)presenter enterPipForCallViewController:(UIViewController *)viewController completion:(void (^)(void))completion { // Check whether the call view controller is actually presented if (viewController.presentingViewController) @@ -4513,7 +4517,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } } -- (void)callPresenter:(CallPresenter *)presenter exitPipForCallViewController:(CallViewController *)viewController completion:(void (^)(void))completion +- (void)callPresenter:(CallPresenter *)presenter exitPipForCallViewController:(UIViewController *)viewController completion:(void (^)(void))completion { if (@available(iOS 13.0, *)) { @@ -4523,39 +4527,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [self presentViewController:viewController animated:YES completion:completion]; } -- (void)callPresenter:(CallPresenter *)presenter presentGroupCallViewController:(JitsiViewController *)viewController completion:(void (^)(void))completion -{ - if (@available(iOS 13.0, *)) - { - viewController.modalPresentationStyle = UIModalPresentationFullScreen; - } - - [self presentViewController:viewController animated:YES completion:completion]; -} - -- (void)callPresenter:(CallPresenter *)presenter dismissGroupCallViewController:(JitsiViewController *)viewController completion:(void (^)(void))completion -{ - // Check whether the call view controller is actually presented - if (viewController.presentingViewController) - { - [viewController.presentingViewController dismissViewControllerAnimated:YES completion:^{ - - if (completion) - { - completion(); - } - - }]; - } - else - { - if (completion) - { - completion(); - } - } -} - #pragma mark - CallBarDelegate - (void)callBarDidTap:(CallBar *)callBar diff --git a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m index 13e9f9221..5323736aa 100644 --- a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m +++ b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m @@ -277,6 +277,20 @@ static const NSString *kJitsiDataErrorKey = @"error"; // Nothing to do } +- (void)participantLeft:(NSDictionary *)data +{ + // TODO: End call with some logic like below? + + /* + [self.jitsiMeetView retrieveParticipantsInfo:^(NSArray * _Nullable participants) { + if (participants.count == 1) + { + + } + }]; + */ +} + - (void)conferenceTerminated:(NSDictionary *)data { if (data[kJitsiDataErrorKey] != nil)