206 lines
9.0 KiB
Swift
206 lines
9.0 KiB
Swift
//
|
|
// Copyright 2021-2024 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
// Please see LICENSE in the repository root for full details.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
@objc protocol RoomParticipantsInviteCoordinatorBridgePresenterDelegate {
|
|
func roomParticipantsInviteCoordinatorBridgePresenterDidStartLoading(_ coordinatorBridgePresenter: RoomParticipantsInviteCoordinatorBridgePresenter)
|
|
func roomParticipantsInviteCoordinatorBridgePresenterDidEndLoading(_ coordinatorBridgePresenter: RoomParticipantsInviteCoordinatorBridgePresenter)
|
|
func roomParticipantsInviteCoordinatorBridgePresenterDidComplete(_ coordinatorBridgePresenter: RoomParticipantsInviteCoordinatorBridgePresenter)
|
|
}
|
|
|
|
/// RoomParticipantsInviteCoordinatorBridgePresenter enables to start ContactsPickerCoordinator from a view controller.
|
|
/// This bridge is used while waiting for global usage of coordinator pattern.
|
|
@objcMembers
|
|
final class RoomParticipantsInviteCoordinatorBridgePresenter: NSObject {
|
|
// MARK: - Properties
|
|
|
|
// MARK: Private
|
|
|
|
private let session: MXSession?
|
|
private let room: MXRoom?
|
|
private let parentSpaceId: String?
|
|
private let currentSearchText: String?
|
|
private var actualParticipants: [Contact]?
|
|
private var invitedParticipants: [Contact]?
|
|
private var userParticipant: Contact?
|
|
private var roomOptions: [RoomOptionListItemViewData] = []
|
|
|
|
private weak var contactsPickerViewController: ContactsTableViewController?
|
|
private weak var currentAlert: UIAlertController?
|
|
private var contactPickerCoordinator: ContactsPickerCoordinator?
|
|
private var optionListCoordinator: OptionListCoordinator?
|
|
private var navigationRouter: NavigationRouterType?
|
|
|
|
// MARK: Public
|
|
|
|
weak var delegate: RoomParticipantsInviteCoordinatorBridgePresenterDelegate?
|
|
|
|
// MARK: - Setup
|
|
|
|
init(session: MXSession?, room: MXRoom?, parentSpaceId: String?) {
|
|
self.session = session
|
|
self.room = room
|
|
self.parentSpaceId = parentSpaceId
|
|
self.currentSearchText = nil
|
|
self.actualParticipants = nil
|
|
self.invitedParticipants = nil
|
|
self.userParticipant = nil
|
|
|
|
super.init()
|
|
}
|
|
|
|
init(session: MXSession?, room: MXRoom?, parentSpaceId: String?, currentSearchText: String? = nil, actualParticipants: [Contact]? = nil, invitedParticipants: [Contact]? = nil, userParticipant: Contact? = nil) {
|
|
self.session = session
|
|
self.room = room
|
|
self.parentSpaceId = parentSpaceId
|
|
self.currentSearchText = currentSearchText
|
|
self.actualParticipants = actualParticipants
|
|
self.invitedParticipants = invitedParticipants
|
|
self.userParticipant = userParticipant
|
|
|
|
super.init()
|
|
}
|
|
|
|
func present(from viewController: UIViewController, animated: Bool) {
|
|
guard let room = self.room else {
|
|
MXLog.error("[RoomParticipantsInviteCoordinatorBridgePresenter] present: nil room found")
|
|
return
|
|
}
|
|
|
|
if let navigationController = viewController.navigationController {
|
|
self.navigationRouter = NavigationRouterStore.shared.navigationRouter(for: navigationController)
|
|
} else {
|
|
self.navigationRouter = nil
|
|
}
|
|
|
|
if let spaceId = self.parentSpaceId, let spaceRoom = self.session?.spaceService.getSpace(withId: spaceId)?.room {
|
|
self.presentRoomSelector(between: room, and: spaceRoom)
|
|
return
|
|
}
|
|
|
|
self.pushContactsPicker(for: room)
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private class RoomOptionListItemViewData: OptionListItemViewData {
|
|
let room: MXRoom
|
|
|
|
init(title: String? = nil,
|
|
detail: String? = nil,
|
|
image: UIImage? = nil,
|
|
room: MXRoom,
|
|
accessoryImage: UIImage? = Asset.Images.chevron.image,
|
|
enabled: Bool = true) {
|
|
self.room = room
|
|
super.init(title: title, detail: detail, image: image, accessoryImage: accessoryImage, enabled: enabled)
|
|
}
|
|
}
|
|
|
|
private func presentRoomSelector(between room: MXRoom, and spaceRoom: MXRoom) {
|
|
let roomName = room.displayName ?? ""
|
|
let spaceName = spaceRoom.displayName ?? ""
|
|
|
|
self.roomOptions = [
|
|
RoomOptionListItemViewData(title: VectorL10n.roomInviteToSpaceOptionTitle(spaceName),
|
|
detail: VectorL10n.roomInviteToSpaceOptionDetail(spaceName, roomName),
|
|
image: Asset.Images.addParticipants.image, room: spaceRoom,
|
|
accessoryImage: Asset.Images.chevron.image),
|
|
RoomOptionListItemViewData(title: VectorL10n.roomInviteToRoomOptionTitle,
|
|
detail: VectorL10n.roomInviteToRoomOptionDetail(spaceName),
|
|
image: Asset.Images.addParticipants.image, room: room,
|
|
accessoryImage: Asset.Images.chevron.image)
|
|
]
|
|
|
|
let coordinator = OptionListCoordinator(parameters: OptionListCoordinatorParameters(title: VectorL10n.roomIntroCellAddParticipantsAction, options: self.roomOptions, navigationRouter: self.navigationRouter))
|
|
coordinator.delegate = self
|
|
coordinator.start()
|
|
|
|
self.optionListCoordinator = coordinator
|
|
}
|
|
|
|
private func pushContactsPicker(for room: MXRoom) {
|
|
guard let session = self.session else {
|
|
MXLog.error("[RoomParticipantsInviteCoordinatorBridgePresenter] pushContactsPicker: nil session found")
|
|
return
|
|
}
|
|
|
|
canInvite(to: room) { [weak self] canInvite in
|
|
guard let self = self else { return }
|
|
|
|
guard canInvite else {
|
|
let message = room.summary?.roomType == .space ? VectorL10n.spaceInviteNotEnoughPermission : VectorL10n.roomInviteNotEnoughPermission
|
|
let alert = UIAlertController(title: VectorL10n.spacesInvitePeople, message: message, preferredStyle: .alert)
|
|
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default, handler: nil))
|
|
self.navigationRouter?.present(alert, animated: true)
|
|
return
|
|
}
|
|
|
|
let coordinator = ContactsPickerCoordinator(session: session,
|
|
room: room,
|
|
initialSearchText: self.currentSearchText,
|
|
actualParticipants: self.actualParticipants,
|
|
invitedParticipants: self.invitedParticipants,
|
|
userParticipant: self.userParticipant,
|
|
navigationRouter: self.navigationRouter)
|
|
coordinator.delegate = self
|
|
coordinator.start()
|
|
|
|
self.contactPickerCoordinator = coordinator
|
|
}
|
|
}
|
|
|
|
private func canInvite(to room: MXRoom, completion: @escaping (Bool) -> Void) {
|
|
guard let userId = self.session?.myUserId else {
|
|
MXLog.error("[RoomParticipantsInviteCoordinatorBridgePresenter] canInvite: userId not found")
|
|
completion(false)
|
|
return
|
|
}
|
|
|
|
room.state { roomState in
|
|
guard let powerLevels = roomState?.powerLevels else {
|
|
MXLog.error("[RoomParticipantsInviteCoordinatorBridgePresenter] canInvite: room powerLevels not found")
|
|
completion(false)
|
|
return
|
|
}
|
|
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
|
|
|
completion(userPowerLevel >= powerLevels.invite)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension RoomParticipantsInviteCoordinatorBridgePresenter: ContactsPickerCoordinatorDelegate {
|
|
func contactsPickerCoordinatorDidStartLoading(_ coordinator: ContactsPickerCoordinatorProtocol) {
|
|
delegate?.roomParticipantsInviteCoordinatorBridgePresenterDidStartLoading(self)
|
|
}
|
|
|
|
func contactsPickerCoordinatorDidEndLoading(_ coordinator: ContactsPickerCoordinatorProtocol) {
|
|
delegate?.roomParticipantsInviteCoordinatorBridgePresenterDidEndLoading(self)
|
|
}
|
|
|
|
func contactsPickerCoordinatorDidClose(_ coordinator: ContactsPickerCoordinatorProtocol) {
|
|
delegate?.roomParticipantsInviteCoordinatorBridgePresenterDidComplete(self)
|
|
}
|
|
}
|
|
|
|
extension RoomParticipantsInviteCoordinatorBridgePresenter: OptionListCoordinatorDelegate {
|
|
func optionListCoordinator(_ coordinator: OptionListCoordinatorProtocol, didSelectOptionAt index: Int) {
|
|
optionListCoordinator = nil
|
|
self.pushContactsPicker(for: roomOptions[index].room)
|
|
}
|
|
|
|
func optionListCoordinator(_ coordinator: OptionListCoordinatorProtocol, didCompleteWithUserDisplayName userDisplayName: String?) {
|
|
optionListCoordinator = nil
|
|
}
|
|
|
|
func optionListCoordinatorDidCancel(_ coordinator: OptionListCoordinatorProtocol) {
|
|
optionListCoordinator = nil
|
|
}
|
|
}
|