element-ios/Riot/Modules/Room/RoomCoordinator.swift

238 lines
8.7 KiB
Swift

// File created from ScreenTemplate
// $ createScreen.sh Room Room
/*
Copyright 2021 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
import UIKit
final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
// MARK: - Properties
// MARK: Private
private let parameters: RoomCoordinatorParameters
private let roomViewController: RoomViewController
private let activityIndicatorPresenter: ActivityIndicatorPresenterType
private var selectedEventId: String?
private var roomDataSourceManager: MXKRoomDataSourceManager {
return MXKRoomDataSourceManager.sharedManager(forMatrixSession: self.parameters.session)
}
/// Indicate true if the Coordinator has started once
private var hasStartedOnce: Bool {
return self.roomViewController.delegate != nil
}
private var navigationRouter: NavigationRouterType? {
var finalNavigationRouter: NavigationRouterType?
if let navigationRouter = self.parameters.navigationRouter {
finalNavigationRouter = navigationRouter
} else if let navigationRouterStore = self.parameters.navigationRouterStore, let currentNavigationController = self.roomViewController.navigationController {
// If no navigationRouter has been provided, try to get the navigation router from the current RoomViewController navigation controller if exists
finalNavigationRouter = navigationRouterStore.navigationRouter(for: currentNavigationController)
}
return finalNavigationRouter
}
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
weak var delegate: RoomCoordinatorDelegate?
var canReleaseRoomDataSource: Bool {
// If the displayed data is not a preview, let the manager release the room data source
// (except if the view controller has the room data source ownership).
return self.parameters.previewData == nil && self.roomViewController.roomDataSource != nil && self.roomViewController.hasRoomDataSourceOwnership == false
}
// MARK: - Setup
init(parameters: RoomCoordinatorParameters) {
self.parameters = parameters
self.selectedEventId = parameters.eventId
self.roomViewController = RoomViewController.instantiate()
self.activityIndicatorPresenter = ActivityIndicatorPresenter()
super.init()
}
// MARK: - Public
func start() {
self.start(withCompletion: nil)
}
// NOTE: Completion closure has been added for legacy architecture purpose.
// Remove this completion after LegacyAppDelegate refactor.
func start(withCompletion completion: (() -> Void)?) {
self.roomViewController.delegate = self
// Detect when view controller has been dismissed by gesture when presented modally (not in full screen).
self.roomViewController.presentationController?.delegate = self
if let eventId = self.selectedEventId {
self.loadRoom(withId: self.parameters.roomId, and: eventId, completion: completion)
} else {
self.loadRoom(withId: self.parameters.roomId, completion: completion)
}
// Add `roomViewController` to the NavigationRouter, only if it has been explicitly set as parameter
if let navigationRouter = self.parameters.navigationRouter {
if navigationRouter.modules.isEmpty == false {
navigationRouter.push(self.roomViewController, animated: true, popCompletion: nil)
} else {
navigationRouter.setRootModule(self.roomViewController, popCompletion: nil)
}
}
}
func start(withEventId eventId: String, completion: (() -> Void)?) {
self.selectedEventId = eventId
if self.hasStartedOnce {
self.loadRoom(withId: self.parameters.roomId, and: eventId, completion: completion)
} else {
self.start(withCompletion: completion)
}
}
func toPresentable() -> UIViewController {
return self.roomViewController
}
// MARK: - Private
private func loadRoom(withId roomId: String, completion: (() -> Void)?) {
// Present activity indicator when retrieving roomDataSource for given room ID
self.activityIndicatorPresenter.presentActivityIndicator(on: roomViewController.view, animated: false)
let roomDataSourceManager: MXKRoomDataSourceManager = MXKRoomDataSourceManager.sharedManager(forMatrixSession: self.parameters.session)
// LIVE: Show the room live timeline managed by MXKRoomDataSourceManager
roomDataSourceManager.roomDataSource(forRoom: roomId, create: true, onComplete: { [weak self] (roomDataSource) in
guard let self = self else {
return
}
self.activityIndicatorPresenter.removeCurrentActivityIndicator(animated: true)
if let roomDataSource = roomDataSource {
self.roomViewController.displayRoom(roomDataSource)
}
completion?()
})
}
private func loadRoom(withId roomId: String, and eventId: String, completion: (() -> Void)?) {
// Present activity indicator when retrieving roomDataSource for given room ID
self.activityIndicatorPresenter.presentActivityIndicator(on: roomViewController.view, animated: false)
// Open the room on the requested event
RoomDataSource.load(withRoomId: roomId,
initialEventId: eventId,
andMatrixSession: self.parameters.session) { [weak self] (dataSource) in
guard let self = self else {
return
}
self.activityIndicatorPresenter.removeCurrentActivityIndicator(animated: true)
guard let roomDataSource = dataSource as? RoomDataSource else {
return
}
roomDataSource.markTimelineInitialEvent = true
self.roomViewController.displayRoom(roomDataSource)
// Give the data source ownership to the room view controller.
self.roomViewController.hasRoomDataSourceOwnership = true
completion?()
}
}
}
// MARK: - RoomIdentifiable
extension RoomCoordinator: RoomIdentifiable {
var roomId: String? {
return self.parameters.roomId
}
var mxSession: MXSession? {
self.parameters.session
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension RoomCoordinator: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
self.delegate?.roomCoordinatorDidDismissInteractively(self)
}
}
// MARK: - RoomViewControllerDelegate
extension RoomCoordinator: RoomViewControllerDelegate {
func roomViewController(_ roomViewController: RoomViewController, showRoomWithId roomID: String) {
self.delegate?.roomCoordinator(self, didSelectRoomWithId: roomID)
}
func roomViewController(_ roomViewController: RoomViewController, showMemberDetails roomMember: MXRoomMember) {
// TODO:
}
func roomViewControllerShowRoomDetails(_ roomViewController: RoomViewController) {
// TODO:
}
func roomViewControllerDidLeaveRoom(_ roomViewController: RoomViewController) {
self.delegate?.roomCoordinatorDidLeaveRoom(self)
}
func roomViewControllerPreviewDidTapCancel(_ roomViewController: RoomViewController) {
self.delegate?.roomCoordinatorDidCancelRoomPreview(self)
}
func roomViewController(_ roomViewController: RoomViewController, startChatWithUserId userId: String, completion: @escaping () -> Void) {
AppDelegate.theDelegate().createDirectChat(withUserId: userId, completion: completion)
}
func roomViewController(_ roomViewController: RoomViewController, showCompleteSecurityFor session: MXSession) {
AppDelegate.theDelegate().presentCompleteSecurity(for: session)
}
func roomViewController(_ roomViewController: RoomViewController, handleUniversalLinkWith parameters: UniversalLinkParameters) -> Bool {
return AppDelegate.theDelegate().handleUniversalLink(with: parameters)
}
}