SP3.1: Update room settings for Spaces #5231

- Update after review
This commit is contained in:
Gil Eluard
2022-02-28 16:07:09 +01:00
parent 3a9b6b248b
commit bca69bb7c8
52 changed files with 878 additions and 519 deletions
@@ -25,6 +25,7 @@ enum RoomAccessCoordinatorCoordinatorAction {
}
@objcMembers
@available(iOS 14.0, *)
final class RoomAccessCoordinator: Coordinator {
// MARK: - Properties
@@ -52,6 +53,8 @@ final class RoomAccessCoordinator: Coordinator {
return parameters.room.roomId
}
private weak var accessCoordinator: RoomAccessTypeChooserCoordinator?
// MARK: - Setup
init(parameters: RoomAccessCoordinatorParameters) {
@@ -62,21 +65,20 @@ final class RoomAccessCoordinator: Coordinator {
func start() {
if #available(iOS 14.0, *) {
MXLog.debug("[RoomAccessCoordinator] did start.")
let rootCoordinator = self.createRoomAccessTypeCoordinator()
rootCoordinator.start()
self.add(childCoordinator: rootCoordinator)
if self.navigationRouter.modules.isEmpty == false {
self.navigationRouter.push(rootCoordinator, animated: true, popCompletion: { [weak self] in
self?.remove(childCoordinator: rootCoordinator)
})
} else {
self.navigationRouter.setRootModule(rootCoordinator) { [weak self] in
self?.remove(childCoordinator: rootCoordinator)
}
MXLog.debug("[RoomAccessCoordinator] did start.")
let rootCoordinator = self.createRoomAccessTypeCoordinator()
rootCoordinator.start()
self.add(childCoordinator: rootCoordinator)
self.accessCoordinator = rootCoordinator
if self.navigationRouter.modules.isEmpty == false {
self.navigationRouter.push(rootCoordinator, animated: true, popCompletion: { [weak self] in
self?.remove(childCoordinator: rootCoordinator)
})
} else {
self.navigationRouter.setRootModule(rootCoordinator) { [weak self] in
self?.remove(childCoordinator: rootCoordinator)
}
}
}
@@ -87,7 +89,6 @@ final class RoomAccessCoordinator: Coordinator {
// MARK: - Private
@available(iOS 14.0, *)
func pushScreen(with coordinator: Coordinator & Presentable) {
add(childCoordinator: coordinator)
@@ -98,7 +99,16 @@ final class RoomAccessCoordinator: Coordinator {
coordinator.start()
}
@available(iOS 14.0, *)
func popupScreen(with coordinator: Coordinator & Presentable) {
add(childCoordinator: coordinator)
coordinator.toPresentable().modalPresentationStyle = .overFullScreen
coordinator.toPresentable().modalTransitionStyle = .crossDissolve
self.navigationRouter.present(coordinator, animated: true)
coordinator.start()
}
private func createRoomAccessTypeCoordinator() -> RoomAccessTypeChooserCoordinator {
let coordinator: RoomAccessTypeChooserCoordinator = RoomAccessTypeChooserCoordinator(parameters: RoomAccessTypeChooserCoordinatorParameters(roomId: parameters.room.roomId, session: parameters.room.mxSession))
coordinator.callback = { [weak self] result in
@@ -112,12 +122,13 @@ final class RoomAccessCoordinator: Coordinator {
case .spaceSelection(let roomId, _):
self.upgradedRoomId = roomId
self.pushScreen(with: self.createRestrictedAccessSpaceChooserCoordinator(with: roomId))
case .roomUpgradeNeeded(let roomId, let versionOverride):
self.popupScreen(with: self.createUpgradeRoomCoordinator(withRoomWithId: roomId, to: versionOverride))
}
}
return coordinator
}
@available(iOS 14.0, *)
private func createRestrictedAccessSpaceChooserCoordinator(with roomId: String) -> MatrixItemChooserCoordinator {
let paramaters = MatrixItemChooserCoordinatorParameters(
session: parameters.room.mxSession,
@@ -139,4 +150,23 @@ final class RoomAccessCoordinator: Coordinator {
return coordinator
}
private func createUpgradeRoomCoordinator(withRoomWithId roomId: String, to versionOverride: String) -> RoomUpgradeCoordinator {
let paramaters = RoomUpgradeCoordinatorParameters(
session: parameters.room.mxSession,
roomId: roomId,
versionOverride: versionOverride)
let coordinator = RoomUpgradeCoordinator(parameters: paramaters)
coordinator.completion = { [weak self] result in
guard let self = self else { return }
self.accessCoordinator?.handleRoomUpgradeResult(result)
self.navigationRouter.dismissModule(animated: true) {
self.remove(childCoordinator: coordinator)
}
}
return coordinator
}
}
@@ -15,6 +15,7 @@
//
import UIKit
@available(iOS 14.0, *)
@objc protocol RoomAccessCoordinatorBridgePresenterDelegate {
func roomAccessCoordinatorBridgePresenterDelegate(_ coordinatorBridgePresenter: RoomAccessCoordinatorBridgePresenter, didCancelRoomWithId roomId: String)
func roomAccessCoordinatorBridgePresenterDelegate(_ coordinatorBridgePresenter: RoomAccessCoordinatorBridgePresenter, didCompleteRoomWithId roomId: String)
@@ -25,6 +26,7 @@ import UIKit
/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers).
/// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator.
@objcMembers
@available(iOS 14.0, *)
final class RoomAccessCoordinatorBridgePresenter: NSObject {
// MARK: - Properties
@@ -85,6 +87,7 @@ final class RoomAccessCoordinatorBridgePresenter: NSObject {
// MARK: - UIAdaptivePresentationControllerDelegate
@available(iOS 14.0, *)
extension RoomAccessCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) {
@@ -63,6 +63,8 @@ final class RoomAccessTypeChooserCoordinator: Coordinator, Presentable {
self.callback?(.done(roomId))
case .cancel(let roomId):
self.callback?(.cancel(roomId))
case .roomUpgradeNeeded(let roomId, let versionOverride):
self.callback?(.roomUpgradeNeeded(roomId, versionOverride))
}
}
}
@@ -70,4 +72,8 @@ final class RoomAccessTypeChooserCoordinator: Coordinator, Presentable {
func toPresentable() -> UIViewController {
return self.roomAccessTypeChooserHostingController
}
func handleRoomUpgradeResult(_ result: RoomUpgradeCoordinatorResult) {
self.roomAccessTypeChooserViewModel.handleRoomUpgradeResult(result)
}
}
@@ -35,6 +35,7 @@ struct RoomAccessTypeChooserAccessItem: Identifiable, Equatable {
/// Actions returned by the coordinator callback
enum RoomAccessTypeChooserCoordinatorAction {
case spaceSelection(String, RoomAccessTypeChooserAccessType)
case roomUpgradeNeeded(String, String)
case done(String)
case cancel(String)
}
@@ -51,6 +52,7 @@ enum RoomAccessTypeChooserStateAction {
/// Actions sent by the`ViewModel` to the `Coordinator`.
enum RoomAccessTypeChooserViewModelAction {
case spaceSelection(String, RoomAccessTypeChooserAccessType)
case roomUpgradeNeeded(String, String)
case done(String)
case cancel(String)
}
@@ -74,6 +76,4 @@ enum RoomAccessTypeChooserViewAction {
case cancel
case done
case didSelectAccessType(RoomAccessTypeChooserAccessType)
case didCancelRoomUpgrade
case didAcceptRoomUpgrade(Bool)
}
@@ -54,10 +54,14 @@ class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAc
.map(RoomAccessTypeChooserStateAction.updateAccessItems)
.eraseToAnyPublisher()
dispatch(actionPublisher: accessTypePublisher)
let showUpgradeRoomAlertPublisher = roomAccessTypeChooserService.roomUpgradeRequiredSubject
.map(RoomAccessTypeChooserStateAction.updateShowUpgradeRoomAlert)
.eraseToAnyPublisher()
dispatch(actionPublisher: showUpgradeRoomAlertPublisher)
roomAccessTypeChooserService
.roomUpgradeRequiredSubject
.sink { [weak self] isUpgradeRequired in
if isUpgradeRequired {
self?.upgradeRoom()
}
}
.store(in: &cancellables)
let waitingMessagePublisher = roomAccessTypeChooserService.waitingMessageSubject
.map(RoomAccessTypeChooserStateAction.updateWaitingMessage)
.eraseToAnyPublisher()
@@ -74,14 +78,6 @@ class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAc
done()
case .cancel:
cancel()
case .didCancelRoomUpgrade:
roomAccessTypeChooserService.upgradeRoom(accepted: false, autoInviteUsers: false) { _, _ in }
case .didAcceptRoomUpgrade(let autoInviteUsers):
roomAccessTypeChooserService.upgradeRoom(accepted: true, autoInviteUsers: autoInviteUsers) { [weak self] upgradeFinished, roomId in
if upgradeFinished {
self?.callback?(.spaceSelection(roomId, .restricted))
}
}
}
}
@@ -97,8 +93,27 @@ class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAc
}
}
func handleRoomUpgradeResult(_ result: RoomUpgradeCoordinatorResult) {
switch result {
case .cancel(let roomId):
roomAccessTypeChooserService.updateRoomId(with: roomId)
case .done(let roomId):
roomAccessTypeChooserService.updateRoomId(with: roomId)
callback?(.spaceSelection(roomId, .restricted))
}
}
// MARK: - Private
private func upgradeRoom() {
guard let versionOverride = roomAccessTypeChooserService.versionOverride else {
MXLog.error("[RoomAccessTypeChooserViewModel] upgradeRoom: versionOverride not found")
return
}
callback?(.roomUpgradeNeeded(roomAccessTypeChooserService.currentRoomId, versionOverride))
}
private func done() {
roomAccessTypeChooserService.applySelection { [weak self] in
guard let self = self else { return }
@@ -20,4 +20,6 @@ protocol RoomAccessTypeChooserViewModelProtocol {
var callback: ((RoomAccessTypeChooserViewModelAction) -> Void)? { get set }
@available(iOS 14, *)
var context: RoomAccessTypeChooserViewModelType.Context { get }
func handleRoomUpgradeResult(_ result: RoomUpgradeCoordinatorResult)
}
@@ -50,7 +50,6 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
}
private var roomJoinRule: MXRoomJoinRule = .private
private var currentOperation: MXHTTPOperation?
private let restrictedVersionOverride: String?
// MARK: Public
@@ -60,6 +59,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
private(set) var errorSubject: CurrentValueSubject<Error?, Never>
private(set) var currentRoomId: String
private(set) var versionOverride: String?
// MARK: - Setup
@@ -67,7 +67,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
self.roomId = roomId
self.session = session
self.currentRoomId = roomId
restrictedVersionOverride = session.homeserverCapabilitiesService.versionOverrideForFeature(.restricted)
self.versionOverride = session.homeserverCapabilitiesService.versionOverrideForFeature(.restricted)
roomUpgradeRequiredSubject = CurrentValueSubject(false)
waitingMessageSubject = CurrentValueSubject(nil)
@@ -85,6 +85,8 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
}
}
// MARK: - Public
func updateSelection(with selectedType: RoomAccessTypeChooserAccessType) {
self.selectedType = selectedType
@@ -97,7 +99,8 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
func applySelection(completion: @escaping () -> Void) {
guard let room = session.room(withRoomId: currentRoomId) else {
fatalError("[RoomAccessTypeChooserService] applySelection: room with ID \(currentRoomId) not found")
MXLog.error("[RoomAccessTypeChooserService] applySelection: room with ID \(currentRoomId) not found")
return
}
let _joinRule: MXRoomJoinRule?
@@ -117,6 +120,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
}
if let joinRule = _joinRule {
self.waitingMessageSubject.send(VectorL10n.roomAccessSettingsScreenSettingRoomAccess)
room.setJoinRule(joinRule) { [weak self] response in
guard let self = self else { return }
@@ -132,38 +136,9 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
}
}
func upgradeRoom(accepted: Bool, autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) {
roomUpgradeRequiredSubject.send(false)
guard let restrictedVersionOverride = restrictedVersionOverride, accepted else {
setupDefaultSelectionType()
completion(false, currentRoomId)
return
}
waitingMessageSubject.send(VectorL10n.roomAccessSettingsScreenUpgradeAlertUpgrading)
if autoInviteUsers, let room = session.room(withRoomId: self.currentRoomId) {
self.currentOperation = room.members { [weak self] response in
guard let self = self else { return }
switch response {
case .success(let members):
let memberIds: [String] = members?.members.compactMap({ member in
guard member.membership == .join, member.userId != self.session.myUserId else {
return nil
}
return member.userId
}) ?? []
self.upgradeRoom(to: restrictedVersionOverride, inviteUsers: memberIds, completion: completion)
case .failure(let error):
self.waitingMessageSubject.send(nil)
self.errorSubject.send(error)
}
}
} else {
self.upgradeRoom(to: restrictedVersionOverride, inviteUsers: [], completion: completion)
}
func updateRoomId(with roomId: String) {
self.currentRoomId = roomId
readRoomState()
}
// MARK: - Private
@@ -188,21 +163,22 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
private func readRoomState() {
guard let room = session.room(withRoomId: currentRoomId) else {
fatalError("[RoomAccessTypeChooserService] readRoomState: room with ID \(currentRoomId) not found")
MXLog.error("[RoomAccessTypeChooserService] readRoomState: room with ID \(currentRoomId) not found")
return
}
room.state { [weak self] state in
guard let self = self else { return }
if let roomVersion = state?.stateEvents(with: .roomCreate)?.last?.wireContent["room_version"] as? String, let homeserverCapabilitiesService = self.session.homeserverCapabilitiesService {
self.roomUpgradeRequired = self.restrictedVersionOverride != nil && !homeserverCapabilitiesService.isFeatureSupported(.restricted, by: roomVersion)
self.roomUpgradeRequired = self.versionOverride != nil && !homeserverCapabilitiesService.isFeatureSupported(.restricted, by: roomVersion)
}
self.roomJoinRule = state?.joinRule ?? .private
self.setupDefaultSelectionType()
}
}
private func setupDefaultSelectionType() {
switch roomJoinRule {
case .restricted:
@@ -212,82 +188,9 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
default:
selectedType = .private
}
}
private func upgradeRoom(to restrictedVersionOverride: String, inviteUsers userIds: [String], completion: @escaping (Bool, String) -> Void) {
// Need to disable graph update during this process as a lot of syncs will occure
session.spaceService.graphUpdateEnabled = false
currentOperation = session.matrixRestClient.upgradeRoom(withId: self.currentRoomId, to: restrictedVersionOverride) { [weak self] response in
guard let self = self else { return }
switch response {
case .success(let replacementRoomId):
let oldRoomId = self.currentRoomId
self.roomUpgradeRequired = false
self.currentRoomId = replacementRoomId
let parentSpaces = self.session.spaceService.directParentIds(ofRoomWithId: oldRoomId)
self.moveRoom(from: oldRoomId, to: replacementRoomId, within: Array(parentSpaces), at: 0) {
self.session.spaceService.graphUpdateEnabled = true
self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] notification in
guard let self = self else { return }
if let observer = self.didBuildSpaceGraphObserver {
NotificationCenter.default.removeObserver(observer)
self.didBuildSpaceGraphObserver = nil
}
DispatchQueue.main.async {
self.inviteUser(from: userIds, at: 0, completion: completion)
}
}
}
case .failure(let error):
self.session.spaceService.graphUpdateEnabled = true
self.waitingMessageSubject.send(nil)
self.errorSubject.send(error)
}
}
}
private func moveRoom(from roomId: String, to newRoomId: String, within parentIds: [String], at index: Int, completion: @escaping () -> Void) {
guard index < parentIds.count else {
completion()
return
}
guard let space = session.spaceService.getSpace(withId: parentIds[index]) else {
MXLog.warning("[RoomAccessTypeChooserService] moveRoom \(roomId) to \(newRoomId) within \(parentIds[index]): space not found")
moveRoom(from: roomId, to: newRoomId, within: parentIds, at: index + 1, completion: completion)
return
}
space.moveChild(withRoomId: roomId, to: newRoomId) { [weak self] response in
guard let self = self else { return }
if let error = response.error {
MXLog.warning("[RoomAccessTypeChooserService] moveRoom \(roomId) to \(newRoomId) within \(space.spaceId): failed due to error: \(error)")
}
self.moveRoom(from: roomId, to: newRoomId, within: parentIds, at: index + 1, completion: completion)
}
}
private func inviteUser(from userIds: [String], at index: Int, completion: @escaping (Bool, String) -> Void) {
guard index < userIds.count else {
self.waitingMessageSubject.send(nil)
completion(true, currentRoomId)
return
}
currentOperation = session.matrixRestClient.invite(.userId(userIds[index]), toRoom: currentRoomId) { [weak self] response in
guard let self = self else { return }
self.currentOperation = nil
if let error = response.error {
MXLog.warning("[RoomAccessTypeChooserService] inviteUser: failed to invite \(userIds[index]) to \(self.currentRoomId) due to error: \(error)")
}
self.inviteUser(from: userIds, at: index + 1, completion: completion)
if selectedType != .restricted {
roomUpgradeRequiredSubject.send(false)
}
}
}
@@ -32,10 +32,11 @@ class MockRoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
private(set) var errorSubject: CurrentValueSubject<Error?, Never>
private(set) var selectedType: RoomAccessTypeChooserAccessType = .private
var currentRoomId: String {
return "sldkfjsdljf:,atrix.org"
var currentRoomId: String = "!aaabaa:matrix.org"
var versionOverride: String? {
return "9"
}
init(accessItems: [RoomAccessTypeChooserAccessItem] = mockAccessItems) {
accessItemsSubject = CurrentValueSubject(accessItems)
roomUpgradeRequiredSubject = CurrentValueSubject(false)
@@ -51,8 +52,8 @@ class MockRoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
}
func upgradeRoom(accepted: Bool, autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) {
func updateRoomId(with roomId: String) {
currentRoomId = roomId
}
func applySelection(completion: @escaping () -> Void) {
@@ -26,8 +26,9 @@ protocol RoomAccessTypeChooserServiceProtocol {
var selectedType: RoomAccessTypeChooserAccessType { get }
var currentRoomId: String { get }
var versionOverride: String? { get }
func updateSelection(with selectedType: RoomAccessTypeChooserAccessType)
func applySelection(completion: @escaping () -> Void)
func upgradeRoom(accepted: Bool, autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void)
func updateRoomId(with roomId: String)
}
@@ -32,16 +32,7 @@ struct RoomAccessTypeChooser: View {
var body: some View {
listContent
.modifier(WaitOverlay(
allowUserInteraction: false,
message: $viewModel.waitingMessage,
isLoading: $viewModel.isLoading))
.modal(withStyle: .overFullScreen,
modalTransitionStyle: .crossDissolve,
id: "RoomAccessTypeChooser-RoomAccessTypeChooserUpgradeRoomAlert",
isPresented: $viewModel.showUpgradeRoomAlert) {
RoomAccessTypeChooserUpgradeRoomAlert(viewModel: viewModel)
}
.waitOverlay(show: viewModel.isLoading, message: viewModel.waitingMessage, allowUserInteraction: false)
.navigationTitle(VectorL10n.roomAccessSettingsScreenNavTitle)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
@@ -57,6 +48,7 @@ struct RoomAccessTypeChooser: View {
.disabled(viewModel.isLoading)
}
}
.accentColor(theme.colors.accent)
}
// MARK: Private
@@ -44,15 +44,9 @@ struct RoomAccessTypeChooserRow: View {
.font(theme.fonts.subheadline)
}
Spacer()
if isSelected {
Image(systemName: "checkmark.circle.fill")
.renderingMode(.template)
.foregroundColor(theme.colors.accent)
} else {
Image(systemName: "circle")
.renderingMode(.template)
.foregroundColor(theme.colors.quarterlyContent)
}
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
.renderingMode(.template)
.foregroundColor(isSelected ? theme.colors.accent : theme.colors.quarterlyContent)
}
if let badgeText = badgeText {
Text(badgeText)
@@ -1,94 +0,0 @@
//
// 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 SwiftUI
@available(iOS 14.0, *)
struct RoomAccessTypeChooserUpgradeRoomAlert: View {
// MARK: - Properties
@ObservedObject var viewModel: RoomAccessTypeChooserViewModelType.Context
@State var autoInviteUsers: Bool = true
// MARK: - Private
@Environment(\.theme) private var theme: ThemeSwiftUI
// MARK: - Public
var body: some View {
ZStack {
Color.black.opacity(0.6)
alertContent
.modifier(WaitOverlay(
allowUserInteraction: false,
message: $viewModel.waitingMessage,
isLoading: $viewModel.isLoading))
}
.edgesIgnoringSafeArea(.all)
}
// MARK: - Private
@ViewBuilder
private var alertContent: some View {
VStack(alignment: .center) {
Text(VectorL10n.roomAccessSettingsScreenUpgradeAlertTitle)
.font(theme.fonts.title3SB)
.foregroundColor(theme.colors.primaryContent)
.padding(.top, 16)
.padding(.bottom, 24)
Text(VectorL10n.roomAccessSettingsScreenUpgradeAlertMessage)
.multilineTextAlignment(.center)
.font(theme.fonts.subheadline)
.foregroundColor(theme.colors.secondaryContent)
.padding(.bottom, 35)
.padding(.horizontal, 12)
Toggle(isOn: $autoInviteUsers, label: {
Text(VectorL10n.roomAccessSettingsScreenUpgradeAlertAutoInviteSwitch)
.font(theme.fonts.body)
.foregroundColor(theme.colors.secondaryContent)
})
.toggleStyle(SwitchToggleStyle(tint: theme.colors.accent))
.padding(.horizontal, 28)
Divider()
.padding(.horizontal, 28)
Button {
viewModel.send(viewAction: .didAcceptRoomUpgrade(autoInviteUsers))
} label: {
Text(VectorL10n.roomAccessSettingsScreenUpgradeAlertUpgradeButton)
}
.buttonStyle(PrimaryActionButtonStyle())
.accessibilityIdentifier("upgradeButton")
.padding(.horizontal, 24)
.padding(.top, 16)
Button {
viewModel.send(viewAction: .didCancelRoomUpgrade)
} label: {
Text(VectorL10n.cancel)
}
.buttonStyle(SecondaryActionButtonStyle())
.accessibilityIdentifier("cancelButton")
.padding(.horizontal, 24)
.padding(.vertical, 16)
}
.background(RoundedRectangle.init(cornerRadius: 8).foregroundColor(theme.colors.background))
.padding(.horizontal, 20)
.frame(minWidth: 0, maxWidth: 500)
}
}
@@ -40,10 +40,6 @@ class RoomRestrictedAccessSpaceChooserItemsProcessor: MatrixItemChooserProcessor
}
func computeSelection(withIds itemsIds: [String], completion: @escaping (Result<Void, Error>) -> Void) {
// DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
// completion(.success(()))
// }
session.matrixRestClient.setRoomJoinRule(.restricted, forRoomWithId: roomId, allowedParentIds: itemsIds) { response in
switch response {
case .failure(let error):
@@ -33,18 +33,21 @@ struct RoomRestrictedAccessSpaceChooserSelector: View {
MatrixItemChooser(viewModel: viewModel, listBottomPadding: nil)
.background(theme.colors.background)
.navigationTitle(VectorL10n.roomAccessSettingsScreenNavTitle)
// .navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(VectorL10n.cancel) {
viewModel.send(viewAction: .cancel)
}
.foregroundColor(viewModel.viewState.loading ? theme.colors.quarterlyContent : theme.colors.accent)
.opacity(viewModel.viewState.loading ? 0.7 : 1)
.disabled(viewModel.viewState.loading)
}
ToolbarItem(placement: .confirmationAction) {
Button(VectorL10n.done) {
viewModel.send(viewAction: .done)
}
.foregroundColor(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? theme.colors.quarterlyContent : theme.colors.accent)
.opacity(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading ? 0.7 : 1)
.disabled(viewModel.viewState.selectedItemIds.isEmpty || viewModel.viewState.loading)
}
}