SP2: Adding Rooms to Spaces #523o

- check permission before adding room
- Added join button in explore room screens
This commit is contained in:
Gil Eluard 2022-02-05 08:20:39 +01:00
parent 601ba0b472
commit 97e22f50aa
13 changed files with 119 additions and 10 deletions

View file

@ -1900,6 +1900,7 @@ Tap the + to start adding people.";
"spaces_invite_people" = "Invite people"; "spaces_invite_people" = "Invite people";
"spaces_add_room" = "Add room"; "spaces_add_room" = "Add room";
"spaces_add_room_missing_permission_message" = "You do not have permissions to add rooms to this space.";
"spaces_add_space" = "Add space"; "spaces_add_space" = "Add space";
// Mark: Avatar // Mark: Avatar

View file

@ -5415,6 +5415,10 @@ public class VectorL10n: NSObject {
public static var spacesAddRoom: String { public static var spacesAddRoom: String {
return VectorL10n.tr("Vector", "spaces_add_room") return VectorL10n.tr("Vector", "spaces_add_room")
} }
/// You do not have permissions to add rooms to this space.
public static var spacesAddRoomMissingPermissionMessage: String {
return VectorL10n.tr("Vector", "spaces_add_room_missing_permission_message")
}
/// Adding rooms coming soon /// Adding rooms coming soon
public static var spacesAddRoomsComingSoonTitle: String { public static var spacesAddRoomsComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_add_rooms_coming_soon_title") return VectorL10n.tr("Vector", "spaces_add_rooms_coming_soon_title")

View file

@ -309,6 +309,22 @@
} }
} }
- (void)createNewRoom
{
if (recentsDataSource.currentSpace) {
[recentsDataSource.currentSpace canAddRoomWithCompletion:^(BOOL canAddRoom) {
if (canAddRoom) {
[super createNewRoom];
} else {
[[AppDelegate theDelegate] showAlertWithTitle:[VectorL10n roomRecentsCreateEmptyRoom]
message:[VectorL10n spacesAddRoomMissingPermissionMessage]];
}
}];
} else {
[super createNewRoom];
}
}
#pragma mark - UITableViewDataSource #pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

View file

@ -393,7 +393,15 @@ extension SideMenuCoordinator: SpaceMenuPresenterDelegate {
case .exploreMembers: case .exploreMembers:
self.showMembers(spaceId: spaceId, session: session) self.showMembers(spaceId: spaceId, session: session)
case .addRoom: case .addRoom:
self.showAddRoom(spaceId: spaceId, session: session) session.spaceService.getSpace(withId: spaceId)?.canAddRoom { canAddRoom in
if canAddRoom {
self.showAddRoom(spaceId: spaceId, session: session)
} else {
let alert = UIAlertController(title: VectorL10n.spacesAddRoom, message: VectorL10n.spacesAddRoomMissingPermissionMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default, handler: nil))
self.toPresentable().present(alert, animated: true, completion: nil)
}
}
case .addSpace: case .addSpace:
AppDelegate.theDelegate().showAlert(withTitle: VectorL10n.spacesAddSpace, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName)) AppDelegate.theDelegate().showAlert(withTitle: VectorL10n.spacesAddSpace, message: VectorL10n.spacesComingSoonDetail(AppInfo.current.displayName))
case .settings: case .settings:

View file

@ -27,6 +27,7 @@ final class SpaceExploreRoomCoordinator: SpaceExploreRoomCoordinatorType {
private var spaceExploreRoomViewModel: SpaceExploreRoomViewModelType private var spaceExploreRoomViewModel: SpaceExploreRoomViewModelType
private let spaceExploreRoomViewController: SpaceExploreRoomViewController private let spaceExploreRoomViewController: SpaceExploreRoomViewController
private let parameters: SpaceExploreRoomCoordinatorParameters
// MARK: Public // MARK: Public
@ -42,6 +43,7 @@ final class SpaceExploreRoomCoordinator: SpaceExploreRoomCoordinatorType {
let spaceExploreRoomViewController = SpaceExploreRoomViewController.instantiate(with: spaceExploreRoomViewModel) let spaceExploreRoomViewController = SpaceExploreRoomViewController.instantiate(with: spaceExploreRoomViewModel)
self.spaceExploreRoomViewModel = spaceExploreRoomViewModel self.spaceExploreRoomViewModel = spaceExploreRoomViewModel
self.spaceExploreRoomViewController = spaceExploreRoomViewController self.spaceExploreRoomViewController = spaceExploreRoomViewController
self.parameters = parameters
} }
// MARK: - Public methods // MARK: - Public methods
@ -70,6 +72,23 @@ extension SpaceExploreRoomCoordinator: SpaceExploreRoomViewModelCoordinatorDeleg
} }
func spaceExploreRoomViewModelDidAddRoom(_ viewModel: SpaceExploreRoomViewModelType) { func spaceExploreRoomViewModelDidAddRoom(_ viewModel: SpaceExploreRoomViewModelType) {
self.delegate?.spaceExploreRoomCoordinatorDidAddRoom(self) guard let space = parameters.session.spaceService.getSpace(withId: parameters.spaceId) else {
showAddRoomMissingPermissionAlert()
return
}
space.canAddRoom { canAddRoom in
if canAddRoom {
self.delegate?.spaceExploreRoomCoordinatorDidAddRoom(self)
} else {
self.showAddRoomMissingPermissionAlert()
}
}
}
private func showAddRoomMissingPermissionAlert() {
let alert = UIAlertController(title: VectorL10n.spacesAddRoom, message: VectorL10n.spacesAddRoomMissingPermissionMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default, handler: nil))
self.toPresentable().present(alert, animated: true, completion: nil)
} }
} }

View file

@ -20,4 +20,5 @@ struct SpaceExploreRoomCoordinatorParameters {
let session: MXSession let session: MXSession
let spaceId: String let spaceId: String
let spaceName: String? let spaceName: String?
let showCancelMenuItem: Bool
} }

View file

@ -24,6 +24,7 @@ enum SpaceExploreRoomViewAction {
case loadData case loadData
case complete(_ selectedItem: SpaceExploreRoomListItemViewData, _ sourceView: UIView?) case complete(_ selectedItem: SpaceExploreRoomListItemViewData, _ sourceView: UIView?)
case searchChanged(_ text: String?) case searchChanged(_ text: String?)
case join
case cancel case cancel
case addRoom case addRoom
} }

View file

@ -125,12 +125,14 @@ final class SpaceExploreRoomViewController: UIViewController {
} }
private func setupViews() { private func setupViews() {
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in if viewModel.showCancelMenuItem {
self?.cancelButtonAction() let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
self?.cancelButtonAction()
}
self.navigationItem.leftBarButtonItem = cancelBarButtonItem
} }
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
self.vc_removeBackTitle() self.vc_removeBackTitle()
self.titleView = MainTitleView() self.titleView = MainTitleView()
@ -145,6 +147,18 @@ final class SpaceExploreRoomViewController: UIViewController {
self.setupTableViewHeader() self.setupTableViewHeader()
} }
private func setupJoinButton(canJoin: Bool) {
if canJoin {
let joinButtonItem = MXKBarButtonItem(title: VectorL10n.join, style: .done) { [weak self] in
self?.viewModel.process(viewAction: .join)
}
self.navigationItem.rightBarButtonItem = joinButtonItem
} else {
self.navigationItem.rightBarButtonItem = nil
}
}
private func setupTableViewHeader() { private func setupTableViewHeader() {
addRoomHeaderView.delegate = self addRoomHeaderView.delegate = self
tableView.tableHeaderView = addRoomHeaderView tableView.tableHeaderView = addRoomHeaderView
@ -176,6 +190,8 @@ final class SpaceExploreRoomViewController: UIViewController {
self.renderEmptyFilterResult() self.renderEmptyFilterResult()
case .error(let error): case .error(let error):
self.render(error: error) self.render(error: error)
case .canJoin(let canJoin):
self.setupJoinButton(canJoin: canJoin)
} }
} }

View file

@ -17,6 +17,7 @@
*/ */
import Foundation import Foundation
import MatrixSDK
final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
@ -32,6 +33,11 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
private var nextBatch: String? private var nextBatch: String?
private var rootSpaceChildInfo: MXSpaceChildInfo? private var rootSpaceChildInfo: MXSpaceChildInfo?
private var canJoin: Bool = false {
didSet {
self.update(viewState: .canJoin(self.canJoin))
}
}
private var itemDataList: [SpaceExploreRoomListItemViewData] = [] { private var itemDataList: [SpaceExploreRoomListItemViewData] = [] {
didSet { didSet {
self.updateFilteredItemList() self.updateFilteredItemList()
@ -56,21 +62,26 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
} }
} }
private var spaceGraphObserver: Any?
// MARK: Public // MARK: Public
weak var viewDelegate: SpaceExploreRoomViewModelViewDelegate? weak var viewDelegate: SpaceExploreRoomViewModelViewDelegate?
weak var coordinatorDelegate: SpaceExploreRoomViewModelCoordinatorDelegate? weak var coordinatorDelegate: SpaceExploreRoomViewModelCoordinatorDelegate?
private(set) var showCancelMenuItem: Bool
// MARK: - Setup // MARK: - Setup
init(parameters: SpaceExploreRoomCoordinatorParameters) { init(parameters: SpaceExploreRoomCoordinatorParameters) {
self.session = parameters.session self.session = parameters.session
self.spaceId = parameters.spaceId self.spaceId = parameters.spaceId
self.spaceName = parameters.spaceName self.spaceName = parameters.spaceName
self.showCancelMenuItem = parameters.showCancelMenuItem
} }
deinit { deinit {
self.cancelOperations() self.cancelOperations()
} }
// MARK: - Public // MARK: - Public
@ -91,6 +102,8 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
self.searchKeyword = newText self.searchKeyword = newText
case .addRoom: case .addRoom:
self.coordinatorDelegate?.spaceExploreRoomViewModelDidAddRoom(self) self.coordinatorDelegate?.spaceExploreRoomViewModelDidAddRoom(self)
case .join:
self.joinSpace()
} }
} }
@ -109,6 +122,8 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
self.update(viewState: .loading) self.update(viewState: .loading)
} }
self.canJoin = self.session.room(withRoomId: spaceId) == nil
self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, paginationToken: self.nextBatch, completion: { [weak self] response in self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, paginationToken: self.nextBatch, completion: { [weak self] response in
guard let self = self else { guard let self = self else {
return return
@ -158,6 +173,9 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
private func cancelOperations() { private func cancelOperations() {
self.currentOperation?.cancel() self.currentOperation?.cancel()
if let observer = self.spaceGraphObserver {
NotificationCenter.default.removeObserver(observer)
}
} }
private func updateFilteredItemList() { private func updateFilteredItemList() {
@ -170,4 +188,26 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
return (itemData.childInfo.name?.lowercased().contains(searchKeyword) ?? false) || (itemData.childInfo.topic?.lowercased().contains(searchKeyword) ?? false) return (itemData.childInfo.name?.lowercased().contains(searchKeyword) ?? false) || (itemData.childInfo.topic?.lowercased().contains(searchKeyword) ?? false)
}) })
} }
private func joinSpace() {
self.update(viewState: .loading)
self.currentOperation = session.joinRoom(spaceId) { [weak self] response in
switch response {
case .success:
self?.spaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main, using: { [weak self] notification in
guard let self = self else { return }
self.currentOperation = nil
if let observer = self.spaceGraphObserver {
NotificationCenter.default.removeObserver(observer)
}
self.canJoin = false
self.update(viewState: .loaded(self.filteredItemDataList, self.nextBatch != nil && (self.searchKeyword ?? "").isEmpty))
})
case .failure(let error):
self?.update(viewState: .error(error))
}
}
}
} }

View file

@ -33,6 +33,7 @@ protocol SpaceExploreRoomViewModelType {
var viewDelegate: SpaceExploreRoomViewModelViewDelegate? { get set } var viewDelegate: SpaceExploreRoomViewModelViewDelegate? { get set }
var coordinatorDelegate: SpaceExploreRoomViewModelCoordinatorDelegate? { get set } var coordinatorDelegate: SpaceExploreRoomViewModelCoordinatorDelegate? { get set }
var showCancelMenuItem: Bool { get }
func process(viewAction: SpaceExploreRoomViewAction) func process(viewAction: SpaceExploreRoomViewAction)
} }

View file

@ -23,6 +23,7 @@ enum SpaceExploreRoomViewState {
case loading case loading
case spaceNameFound(_ spaceName: String) case spaceNameFound(_ spaceName: String)
case loaded(_ children: [SpaceExploreRoomListItemViewData], _ hasMore: Bool) case loaded(_ children: [SpaceExploreRoomListItemViewData], _ hasMore: Bool)
case canJoin(Bool)
case emptySpace case emptySpace
case emptyFilterResult case emptyFilterResult
case error(Error) case error(Error)

View file

@ -124,7 +124,7 @@ final class ExploreRoomCoordinator: NSObject, ExploreRoomCoordinatorType {
} }
private func createShowSpaceExploreRoomCoordinator(session: MXSession, spaceId: String, spaceName: String?) -> SpaceExploreRoomCoordinator { private func createShowSpaceExploreRoomCoordinator(session: MXSession, spaceId: String, spaceName: String?) -> SpaceExploreRoomCoordinator {
let coordinator = SpaceExploreRoomCoordinator(parameters: SpaceExploreRoomCoordinatorParameters(session: session, spaceId: spaceId, spaceName: spaceName)) let coordinator = SpaceExploreRoomCoordinator(parameters: SpaceExploreRoomCoordinatorParameters(session: session, spaceId: spaceId, spaceName: spaceName, showCancelMenuItem: self.navigationRouter.modules.isEmpty))
coordinator.delegate = self coordinator.delegate = self
return coordinator return coordinator
} }

1
changelog.d/5230.feature Normal file
View file

@ -0,0 +1 @@
Adding Rooms to Spaces