2020-09-04 09:39:45 +00:00
|
|
|
/*
|
2020-09-24 13:16:51 +00:00
|
|
|
Copyright 2020 New Vector Ltd
|
2020-09-04 09:39:45 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2021-05-20 20:11:09 +00:00
|
|
|
/// SplitViewCoordinatorParameters input parameters
|
|
|
|
class SplitViewCoordinatorParameters {
|
|
|
|
|
|
|
|
let router: RootRouterType
|
|
|
|
let userSessionsService: UserSessionsService
|
2021-06-07 16:41:55 +00:00
|
|
|
let appNavigator: AppNavigatorProtocol
|
2021-05-20 20:11:09 +00:00
|
|
|
|
2021-06-07 16:41:55 +00:00
|
|
|
init(router: RootRouterType, userSessionsService: UserSessionsService, appNavigator: AppNavigatorProtocol) {
|
2021-05-20 20:11:09 +00:00
|
|
|
self.router = router
|
|
|
|
self.userSessionsService = userSessionsService
|
2021-06-07 16:41:55 +00:00
|
|
|
self.appNavigator = appNavigator
|
2021-05-20 20:11:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-04 09:39:45 +00:00
|
|
|
final class SplitViewCoordinator: NSObject, SplitViewCoordinatorType {
|
|
|
|
|
|
|
|
// MARK: - Properties
|
|
|
|
|
2021-05-20 20:11:09 +00:00
|
|
|
// MARK: Private
|
2020-09-04 09:39:45 +00:00
|
|
|
|
2021-05-20 20:11:09 +00:00
|
|
|
private let parameters: SplitViewCoordinatorParameters
|
2020-09-04 09:39:45 +00:00
|
|
|
|
|
|
|
private let splitViewController: UISplitViewController
|
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
private weak var masterPresentable: SplitViewMasterPresentable?
|
2021-01-19 12:07:25 +00:00
|
|
|
private var detailNavigationController: UINavigationController?
|
2020-09-04 09:39:45 +00:00
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
private weak var tabBarCoordinator: TabBarCoordinatorType?
|
2020-09-04 09:39:45 +00:00
|
|
|
|
|
|
|
// MARK: Public
|
|
|
|
|
|
|
|
var childCoordinators: [Coordinator] = []
|
|
|
|
|
2020-09-24 09:37:24 +00:00
|
|
|
weak var delegate: SplitViewCoordinatorDelegate?
|
|
|
|
|
2020-09-04 09:39:45 +00:00
|
|
|
// MARK: - Setup
|
2021-05-20 20:11:09 +00:00
|
|
|
|
|
|
|
init(parameters: SplitViewCoordinatorParameters) {
|
|
|
|
self.parameters = parameters
|
2020-09-04 09:39:45 +00:00
|
|
|
|
2021-04-07 12:21:19 +00:00
|
|
|
let splitViewController = RiotSplitViewController()
|
2020-09-04 09:39:45 +00:00
|
|
|
splitViewController.preferredDisplayMode = .allVisible
|
|
|
|
self.splitViewController = splitViewController
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Public methods
|
|
|
|
|
|
|
|
func start() {
|
|
|
|
self.splitViewController.delegate = self
|
2020-09-07 08:06:03 +00:00
|
|
|
|
|
|
|
let tabBarCoordinator = self.createTabBarCoordinator()
|
|
|
|
tabBarCoordinator.delegate = self
|
|
|
|
tabBarCoordinator.splitViewMasterPresentableDelegate = self
|
|
|
|
tabBarCoordinator.start()
|
2020-09-24 14:25:10 +00:00
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
let detailNavigationController = self.createDetailNavigationController()
|
|
|
|
|
|
|
|
self.splitViewController.viewControllers = [tabBarCoordinator.toPresentable(), detailNavigationController]
|
|
|
|
|
|
|
|
self.add(childCoordinator: tabBarCoordinator)
|
|
|
|
|
|
|
|
self.tabBarCoordinator = tabBarCoordinator
|
|
|
|
self.masterPresentable = tabBarCoordinator
|
|
|
|
self.detailNavigationController = detailNavigationController
|
|
|
|
|
2021-05-20 20:11:09 +00:00
|
|
|
self.parameters.router.setRootModule(self.splitViewController)
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func toPresentable() -> UIViewController {
|
|
|
|
return self.splitViewController
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Do not expose publicly this method
|
|
|
|
func restorePlaceholderDetails() {
|
|
|
|
// Be sure that the primary is then visible too.
|
|
|
|
if splitViewController.displayMode == .primaryHidden {
|
|
|
|
splitViewController.preferredDisplayMode = .allVisible
|
|
|
|
}
|
|
|
|
|
|
|
|
if splitViewController.viewControllers.count == 2 {
|
|
|
|
let mainViewController = splitViewController.viewControllers[0]
|
|
|
|
|
|
|
|
let emptyDetailsViewController = self.createPlaceholderDetailsViewController()
|
|
|
|
|
|
|
|
splitViewController.viewControllers = [mainViewController, emptyDetailsViewController]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release the current selected item (room/contact/group...).
|
2020-09-07 08:06:03 +00:00
|
|
|
self.tabBarCoordinator?.releaseSelectedItems()
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func popToHome(animated: Bool, completion: (() -> Void)?) {
|
2020-09-07 08:06:03 +00:00
|
|
|
if let secondNavController = self.detailNavigationController {
|
2020-09-04 09:39:45 +00:00
|
|
|
secondNavController.popToRootViewController(animated: animated)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Force back to the main screen if this is not the one that is displayed
|
2020-09-07 08:06:03 +00:00
|
|
|
self.tabBarCoordinator?.popToHome(animated: animated, completion: completion)
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Private methods
|
|
|
|
|
|
|
|
private func createPlaceholderDetailsViewController() -> UIViewController {
|
2020-09-07 08:06:03 +00:00
|
|
|
return PlaceholderDetailViewController.instantiate()
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
private func createTabBarCoordinator() -> TabBarCoordinator {
|
2021-05-20 20:11:09 +00:00
|
|
|
|
2021-06-07 16:41:55 +00:00
|
|
|
let coordinatorParameters = TabBarCoordinatorParameters(userSessionsService: self.parameters.userSessionsService, appNavigator: self.parameters.appNavigator)
|
2021-05-20 20:11:09 +00:00
|
|
|
|
|
|
|
let tabBarCoordinator = TabBarCoordinator(parameters: coordinatorParameters)
|
2020-09-07 08:06:03 +00:00
|
|
|
tabBarCoordinator.delegate = self
|
|
|
|
return tabBarCoordinator
|
|
|
|
}
|
|
|
|
|
|
|
|
private func createDetailNavigationController() -> UINavigationController {
|
|
|
|
let placeholderDetailViewController = self.createPlaceholderDetailsViewController()
|
|
|
|
let detailNavigationController = RiotNavigationController(rootViewController: placeholderDetailViewController)
|
|
|
|
return detailNavigationController
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - UISplitViewControllerDelegate
|
|
|
|
extension SplitViewCoordinator: UISplitViewControllerDelegate {
|
|
|
|
|
|
|
|
func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? {
|
2020-09-07 08:06:03 +00:00
|
|
|
|
|
|
|
if let detailViewController = self.masterPresentable?.secondViewControllerWhenSeparatedFromPrimary() {
|
|
|
|
return detailViewController
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Else return the default empty details view controller from the storyboard.
|
|
|
|
// Be sure that the primary is then visible too.
|
|
|
|
if splitViewController.displayMode == .primaryHidden {
|
|
|
|
splitViewController.preferredDisplayMode = .allVisible
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.createPlaceholderDetailsViewController()
|
|
|
|
}
|
|
|
|
|
|
|
|
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
|
2020-09-07 08:06:03 +00:00
|
|
|
return self.masterPresentable?.collapseDetailViewController ?? false
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
/// MARK: - UINavigationControllerDelegate
|
|
|
|
extension SplitViewCoordinator: TabBarCoordinatorDelegate {
|
2020-09-24 09:37:24 +00:00
|
|
|
func tabBarCoordinatorDidCompleteAuthentication(_ coordinator: TabBarCoordinatorType) {
|
|
|
|
self.delegate?.splitViewCoordinatorDidCompleteAuthentication(self)
|
|
|
|
}
|
2020-09-07 08:06:03 +00:00
|
|
|
}
|
2020-09-04 09:39:45 +00:00
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
/// MARK: - SplitViewMasterPresentableDelegate
|
|
|
|
extension SplitViewCoordinator: SplitViewMasterPresentableDelegate {
|
|
|
|
func splitViewMasterPresentable(_ presentable: Presentable, wantsToDisplay detailPresentable: Presentable) {
|
2021-06-03 08:30:07 +00:00
|
|
|
MXLog.debug("[SplitViewCoordinator] splitViewMasterPresentable: \(presentable) wantsToDisplay detailPresentable: \(detailPresentable)")
|
2021-01-14 13:54:34 +00:00
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
guard let detailNavigationController = self.detailNavigationController else {
|
2021-06-03 08:30:07 +00:00
|
|
|
MXLog.debug("[SplitViewCoordinator] splitViewMasterPresentable: Failed to display because detailNavigationController is nil")
|
2020-09-07 08:06:03 +00:00
|
|
|
return
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
|
2020-09-07 08:06:03 +00:00
|
|
|
detailNavigationController.viewControllers = [detailPresentable.toPresentable()]
|
|
|
|
self.splitViewController.showDetailViewController(detailNavigationController, sender: nil)
|
2020-09-04 09:39:45 +00:00
|
|
|
}
|
|
|
|
}
|