From 8da856e620662940534cf5be09f8ae42d6790451 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:46:02 +0000 Subject: [PATCH] Add space management to the flows. (#4978) * Add the menu entries to add/remove rooms to/from a space. * Add a user indicator to SpaceAddRoomsScreen. * Reset the SpaceRoomListProxy after adding/removing any children. * Calm the animations down a bit when entering EditMode on the SpaceScreen. --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../SpaceFlowCoordinator.swift | 42 +++++++ .../Mocks/Generated/GeneratedMocks.swift | 35 ++++++ .../Screens/Spaces/Common/SpaceRoomCell.swift | 6 +- .../SpaceAddRoomsScreenViewModel.swift | 30 ++++- .../SpaceScreen/SpaceScreenCoordinator.swift | 3 + .../SpaceScreen/SpaceScreenModels.swift | 3 + .../SpaceScreen/SpaceScreenViewModel.swift | 6 + .../Spaces/SpaceScreen/View/SpaceScreen.swift | 110 +++++++++--------- .../Services/Spaces/SpaceRoomListProxy.swift | 4 + .../Spaces/SpaceRoomListProxyProtocol.swift | 16 +++ .../spaceRoomCell.iPad-en-GB-0.png | 4 +- .../spaceRoomCell.iPad-pseudo-0.png | 4 +- .../spaceRoomCell.iPhone-en-GB-0.png | 4 +- .../spaceRoomCell.iPhone-pseudo-0.png | 4 +- .../spaceScreen.Managing-iPad-en-GB.png | 4 +- .../spaceScreen.Managing-iPad-pseudo.png | 4 +- .../spaceScreen.Managing-iPhone-en-GB.png | 4 +- .../spaceScreen.Managing-iPhone-pseudo.png | 4 +- .../PreviewTests/spaceScreen.iPad-en-GB-0.png | 4 +- .../spaceScreen.iPad-pseudo-0.png | 4 +- .../spaceScreen.iPhone-en-GB-0.png | 4 +- .../spaceScreen.iPhone-pseudo-0.png | 4 +- .../spacesScreen.iPhone-en-GB-0.png | 4 +- .../spacesScreen.iPhone-pseudo-0.png | 4 +- .../SpaceAddRoomsScreenViewModelTests.swift | 6 +- .../Sources/SpaceScreenViewModelTests.swift | 1 + project.yml | 2 +- 29 files changed, 237 insertions(+), 89 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 2483d20e2..233bc6646 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -9791,7 +9791,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 26.1.13; + version = "26.01.20-2"; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index ad14ba5e3..c2cc9edcf 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -158,8 +158,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "134161b4a42d019befe6a9a293d5248b8c41015a", - "version" : "26.1.13" + "revision" : "3c8b43e1203022ca1bc187fe41f48992958b02d0", + "version" : "26.1.20-2" } }, { diff --git a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift index adb16c000..eb67ab559 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift @@ -52,6 +52,8 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { case joinSpace /// The root screen for this flow. case space + /// The user is adding rooms to the space. + case addingRooms /// A child (space) flow is in progress. case presentingChild(childSpaceID: String, previousState: State) /// A room flow is in progress @@ -77,6 +79,11 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { /// The space screen left the space. case leftSpace + /// Allow the user to add existing rooms to this space. + case addRooms + /// The user finished adding rooms to this space. + case dismissedAddRooms + /// Request the presentation of a child space flow. /// /// The space's `SpaceRoomListProxyProtocol` must be provided in the `userInfo`. @@ -145,6 +152,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { } else { navigationStackCoordinator.setRootCoordinator(nil, animated: animated) } + case .addingRooms: + navigationStackCoordinator.setSheetCoordinator(nil) + clearRoute(animated: animated) // Re-run with the state machine back in the .space state. case .presentingChild: childSpaceFlowCoordinator?.clearRoute(animated: animated) clearRoute(animated: animated) // Re-run with the state machine back in the .space state. @@ -182,6 +192,11 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { self?.clearRoute(animated: true) } + stateMachine.addRoutes(event: .addRooms, transitions: [.space => .addingRooms]) { [weak self] _ in + self?.presentSpaceAddRoomsScreen() + } + stateMachine.addRoutes(event: .dismissedAddRooms, transitions: [.addingRooms => .space]) + stateMachine.addRouteMapping { event, fromState, userInfo in guard event == .startChildFlow else { return nil } guard let childEntryPoint = userInfo as? SpaceFlowCoordinatorEntryPoint else { fatalError("An entry point must be provided.") } @@ -306,6 +321,8 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.startSettingsFlow, userInfo: roomProxy) case .displayRolesAndPermissions(let roomProxy): stateMachine.tryEvent(.startRolesAndPermissionsFlow, userInfo: roomProxy) + case .addExistingChildren: + stateMachine.tryEvent(.addRooms) } } .store(in: &cancellables) @@ -371,6 +388,31 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { presentSpace() } + private func presentSpaceAddRoomsScreen() { + guard case let .space(spaceRoomListProxy) = entryPoint else { fatalError("Attempting to show a space with the wrong entry point.") } + + let stackCoordinator = NavigationStackCoordinator() + let parameters = SpaceAddRoomsScreenCoordinatorParameters(spaceRoomListProxy: spaceRoomListProxy, + userSession: flowParameters.userSession, + roomSummaryProvider: flowParameters.userSession.clientProxy.alternateRoomSummaryProvider, + userIndicatorController: flowParameters.userIndicatorController) + let coordinator = SpaceAddRoomsScreenCoordinator(parameters: parameters) + coordinator.actions + .sink { [weak self] action in + guard let self else { return } + switch action { + case .dismiss: + navigationStackCoordinator.setSheetCoordinator(nil) + } + } + .store(in: &cancellables) + + stackCoordinator.setRootCoordinator(coordinator) + navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissedAddRooms) + } + } + // MARK: - Other flows private func startChildFlow(with entryPoint: SpaceFlowCoordinatorEntryPoint) { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 1c74e8767..46460c31d 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -16772,6 +16772,41 @@ class SpaceRoomListProxyMock: SpaceRoomListProxyProtocol, @unchecked Sendable { paginateCallsCount += 1 await paginateClosure?() } + //MARK: - reset + + var resetUnderlyingCallsCount = 0 + var resetCallsCount: Int { + get { + if Thread.isMainThread { + return resetUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = resetUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + resetUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + resetUnderlyingCallsCount = newValue + } + } + } + } + var resetCalled: Bool { + return resetCallsCount > 0 + } + var resetClosure: (() async -> Void)? + + func reset() async { + resetCallsCount += 1 + await resetClosure?() + } } class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { diff --git a/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift b/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift index a4b116424..b6e101290 100644 --- a/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift +++ b/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift @@ -63,7 +63,8 @@ struct SpaceRoomCell: View { action(.select(spaceServiceRoom)) } label: { HStack(spacing: 0) { - if isEditModeActive { + if isEditModeActive, + !spaceServiceRoom.isSpace { // We only support selection of rooms (so don't show this while removing the cell). ZStack { ListRowAccessory.multiSelection(isSelected) } @@ -87,6 +88,9 @@ struct SpaceRoomCell: View { } } .padding(.horizontal, horizontalInsets) + // Ensure the EditMode transition stays inside this cell if there are other insertions/removals in the list. + // Seems to slow down the animations a bit in Xcode previews but its fine in the simulator and on a device. + .drawingGroup() .accessibilityElement(children: .combine) } .buttonStyle(SpaceRoomCellButtonStyle(isHighlighted: isHighlighted)) diff --git a/ElementX/Sources/Screens/Spaces/SpaceAddRoomsScreen/SpaceAddRoomsScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceAddRoomsScreen/SpaceAddRoomsScreenViewModel.swift index 976cf8a9c..a262c270d 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceAddRoomsScreen/SpaceAddRoomsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceAddRoomsScreen/SpaceAddRoomsScreenViewModel.swift @@ -128,15 +128,43 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo } private func save() async { + showSavingIndicator() + defer { hideSavingIndicator() } + for room in state.selectedRooms { if case .failure(let error) = await spaceServiceProxy.addChild(room.id, to: spaceRoomListProxy.id) { MXLog.error("Failed adding room to space: \(error)") - userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown)) + showErrorIndicator() updateRooms() // Hide any rooms that were already added. return } } + await spaceRoomListProxy.resetAndWaitForFullReload(timeout: .seconds(10)) + actionsSubject.send(.dismiss) } + + // MARK: User Indicators + + private var savingIndicatorID: String { "\(Self.self)-Saving" } + private var failureIndicatorID: String { "\(Self.self)-Failure" } + + private func showSavingIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: savingIndicatorID, + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false), + title: L10n.commonSaving, + persistent: true)) + } + + private func hideSavingIndicator() { + userIndicatorController.retractIndicatorWithId(savingIndicatorID) + } + + private func showErrorIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: failureIndicatorID, + type: .toast, + title: L10n.errorUnknown, + iconName: "xmark")) + } } diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift index f00f3ed77..393de74cc 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift @@ -28,6 +28,7 @@ enum SpaceScreenCoordinatorAction { case displayMembers(roomProxy: JoinedRoomProxyProtocol) case displaySpaceSettings(roomProxy: JoinedRoomProxyProtocol) case displayRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol) + case addExistingChildren } final class SpaceScreenCoordinator: CoordinatorProtocol { @@ -72,6 +73,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.displaySpaceSettings(roomProxy: roomProxy)) case .presentRolesAndPermissions(let roomProxy): actionsSubject.send(.displayRolesAndPermissions(roomProxy: roomProxy)) + case .addExistingChildren: + actionsSubject.send(.addExistingChildren) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift index bdd4ba889..92bcb5356 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift @@ -16,6 +16,7 @@ enum SpaceScreenViewModelAction { case presentRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol) case displayMembers(roomProxy: JoinedRoomProxyProtocol) case displaySpaceSettings(roomProxy: JoinedRoomProxyProtocol) + case addExistingChildren } struct SpaceScreenViewState: BindableState { @@ -32,6 +33,7 @@ struct SpaceScreenViewState: BindableState { var canEditBaseInfo = false var canEditRolesAndPermissions = false var canEditSecurityAndPrivacy = false + var canEditChildren = false var editMode: EditMode = .inactive var editModeSelectedIDs: Set = [] @@ -65,6 +67,7 @@ enum SpaceScreenViewAction { case leaveSpace case spaceSettings(roomProxy: JoinedRoomProxyProtocol) case displayMembers(roomProxy: JoinedRoomProxyProtocol) + case addExistingRooms case manageChildren case removeSelectedChildren case confirmRemoveSelectedChildren diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift index 823e182b5..691a2fa86 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift @@ -89,12 +89,14 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc state.canEditBaseInfo = false state.canEditRolesAndPermissions = false state.canEditSecurityAndPrivacy = false + state.canEditChildren = false return } state.canEditBaseInfo = powerLevels.canOwnUserEditBaseInfo() state.canEditRolesAndPermissions = powerLevels.canOwnUserEditRolesAndPermissions() state.canEditSecurityAndPrivacy = powerLevels.canOwnUserEditSecurityAndPrivacy(isSpace: roomInfo.isSpace, joinRule: roomInfo.joinRule) + state.canEditChildren = powerLevels.canOwnUser(sendStateEvent: .spaceChild) } .store(in: &cancellables) } @@ -134,6 +136,8 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc actionsSubject.send(.displayMembers(roomProxy: roomProxy)) case .spaceSettings(let roomProxy): actionsSubject.send(.displaySpaceSettings(roomProxy: roomProxy)) + case .addExistingRooms: + actionsSubject.send(.addExistingChildren) case .manageChildren: withAnimation(.easeOut(duration: 0.25).disabledDuringTests()) { state.editMode = .transient @@ -196,6 +200,8 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc } } + await spaceRoomListProxy.resetAndWaitForFullReload(timeout: .seconds(10)) + process(viewAction: .finishManagingChildren) } diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift index 83bca26e6..a4887f625 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift @@ -27,17 +27,11 @@ struct SpaceScreen: View { } .environment(\.editMode, .constant(context.viewState.editMode)) .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) - .toolbarRole(isEditModeActive ? .automatic : RoomHeaderView.toolbarRole) + .toolbarRole(RoomHeaderView.toolbarRole) .navigationTitle(context.viewState.space.name) .navigationBarTitleDisplayMode(.inline) .navigationBarBackButtonHidden(isEditModeActive) - .toolbar { - if isEditModeActive { - editModeToolbar - } else { - toolbar - } - } + .toolbar { toolbar } .sheet(isPresented: $context.isPresentingRemoveChildrenConfirmation) { SpaceRemoveChildrenConfirmationView(spaceName: context.viewState.space.name) { context.send(viewAction: .confirmRemoveSelectedChildren) @@ -67,6 +61,14 @@ struct SpaceScreen: View { @ToolbarContentBuilder var toolbar: some ToolbarContent { + if isEditModeActive { + ToolbarItem(placement: .cancellationAction) { + Button(L10n.actionCancel, role: .cancel) { + context.send(viewAction: .finishManagingChildren) + } + } + } + // Use the same trick as the RoomScreen for a leading title view that // also hides the navigation title. ToolbarItem(placement: .principal) { @@ -80,62 +82,62 @@ struct SpaceScreen: View { } } - // This should really use a ToolbarItemGroup(placement: .secondaryAction), however it - // was crashing on iOS 26.0 when tapping the ShareLink as the popover presentation - // controller attempts to anchor itself to the button that is no longer visible. - ToolbarItem(placement: .primaryAction) { - Menu { - Section { - if let roomProxy = context.viewState.roomProxy { - Button { context.send(viewAction: .displayMembers(roomProxy: roomProxy)) } label: { - Label(L10n.screenSpaceMenuActionMembers, icon: \.user) - } - } - if let permalink = context.viewState.permalink { - ShareLink(item: permalink) { - Label(L10n.actionShare, icon: \.shareIos) + if isEditModeActive { + ToolbarItem(placement: .primaryAction) { + ToolbarButton(role: .destructive(title: L10n.actionRemove)) { + context.send(viewAction: .removeSelectedChildren) + } + .disabled(context.viewState.editModeSelectedIDs.isEmpty) + } + } else { + // This should really use a ToolbarItemGroup(placement: .secondaryAction), however it + // was crashing on iOS 26.0 when tapping the ShareLink as the popover presentation + // controller attempts to anchor itself to the button that is no longer visible. + ToolbarItem(placement: .primaryAction) { + Menu { + if true { + Section { + Button { context.send(viewAction: .addExistingRooms) } label: { + Label(L10n.actionAddExistingRooms, icon: \.room) + } + Button { context.send(viewAction: .manageChildren) } label: { + Label(L10n.actionManageRooms, icon: \.edit) + } } } - if context.viewState.isSpaceManagementEnabled, - let roomProxy = context.viewState.roomProxy { - Button { context.send(viewAction: .spaceSettings(roomProxy: roomProxy)) } label: { - Label(L10n.commonSettings, icon: \.settings) + Section { + if let roomProxy = context.viewState.roomProxy { + Button { context.send(viewAction: .displayMembers(roomProxy: roomProxy)) } label: { + Label(L10n.screenSpaceMenuActionMembers, icon: \.user) + } + } + if let permalink = context.viewState.permalink { + ShareLink(item: permalink) { + Label(L10n.actionShare, icon: \.shareIos) + } + } + + if context.viewState.isSpaceManagementEnabled, + let roomProxy = context.viewState.roomProxy { + Button { context.send(viewAction: .spaceSettings(roomProxy: roomProxy)) } label: { + Label(L10n.commonSettings, icon: \.settings) + } } } - } - - Section { - Button(role: .destructive) { context.send(viewAction: .leaveSpace) } label: { - Label(L10n.actionLeaveSpace, icon: \.leave) + + Section { + Button(role: .destructive) { context.send(viewAction: .leaveSpace) } label: { + Label(L10n.actionLeaveSpace, icon: \.leave) + } } + } label: { + // Use an SF Symbol to match what ToolbarItemGroup(placement: .secondaryAction) would give us. + Image(systemSymbol: .ellipsis) } - } label: { - // Use an SF Symbol to match what ToolbarItemGroup(placement: .secondaryAction) would give us. - Image(systemSymbol: .ellipsis) } } } - - @ToolbarContentBuilder - var editModeToolbar: some ToolbarContent { - ToolbarItem(placement: .cancellationAction) { - Button(L10n.actionCancel, role: .cancel) { - context.send(viewAction: .finishManagingChildren) - } - } - - ToolbarItem(placement: .principal) { - Text(L10n.commonSelectedCount(context.viewState.editModeSelectedIDs.count)) - } - - ToolbarItem(placement: .primaryAction) { - ToolbarButton(role: .destructive(title: L10n.actionRemove)) { - context.send(viewAction: .removeSelectedChildren) - } - .disabled(context.viewState.editModeSelectedIDs.isEmpty) - } - } } // MARK: - Previews diff --git a/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift b/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift index 30ca9b77f..d0b4cb781 100644 --- a/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift +++ b/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift @@ -60,6 +60,10 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol { } } + func reset() async { + await spaceRoomList.reset() + } + // MARK: - Private private func handleUpdates(_ updates: [SpaceListUpdate]) { diff --git a/ElementX/Sources/Services/Spaces/SpaceRoomListProxyProtocol.swift b/ElementX/Sources/Services/Spaces/SpaceRoomListProxyProtocol.swift index 3f799fdb7..52362d5ff 100644 --- a/ElementX/Sources/Services/Spaces/SpaceRoomListProxyProtocol.swift +++ b/ElementX/Sources/Services/Spaces/SpaceRoomListProxyProtocol.swift @@ -22,4 +22,20 @@ protocol SpaceRoomListProxyProtocol { var paginationStatePublisher: CurrentValuePublisher { get } func paginate() async + func reset() async +} + +extension SpaceRoomListProxyProtocol { + /// Resets the list and then waits everything to be paginated back in again before returning. + /// + /// **Note:** It's the caller's responsibility to handle the calls to ``paginate``. This method + /// purely acts as a helper to wait until the list has reloaded. + func resetAndWaitForFullReload(timeout: Duration) async { + await reset() + + let runner = ExpiringTaskRunner { [paginationStatePublisher] in + await _ = paginationStatePublisher.values.first { $0 == .idle(endReached: true) } + } + try? await runner.run(timeout: timeout) + } } diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-en-GB-0.png index 59231a048..a06b9126a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5511435ffbb116306de56c4fe13874f90cc12eabf83b2589ba9a1adad4080238 -size 253938 +oid sha256:21c3bf8bb04de6c1896b1955f0785d8ffc9b15898205b1c6ea68638d729db47a +size 254978 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-pseudo-0.png index 6b6cfcc91..c147891de 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPad-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0dc15c6e2798e677ab80ec5ee6f2e22d32faddccdc47e2f52b433bad0ca4ec94 -size 296429 +oid sha256:88ae666e2969417e9b03925bdd23b863d8b4c1cd93b86a00cfb76a78b93e6ad1 +size 297539 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-en-GB-0.png index 43f963304..fc23da405 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34754363cd2c7886e42caba103759f6fdb63af2e28a23de910573d266d7f4b82 -size 193936 +oid sha256:d0f77bba1b2b3cbfc2c61639c2b2e585a8dba2e3955e4d3b329fc5e8113fdc16 +size 194831 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-pseudo-0.png index 2edeeb587..06c0b0003 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceRoomCell.iPhone-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dee1473c832480b2adf30bf5a1900ff3d94a55400d651baafabdef1ed0e445d2 -size 226188 +oid sha256:781bd4e44a9912bbe293b5111f3579cf74235fb17de33114c2849077ea69e932 +size 227203 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-en-GB.png index 4dabc33ed..2d7e9faf0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-en-GB.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-en-GB.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b68d646d3cc7e109b242dab25985c9311129f4625c61b0fceabfde8befbe2a2 -size 139161 +oid sha256:a981d66c5c9f6edccbe959b4cfbe431b8e67e0bd736b16f39638be62a5297b7c +size 141054 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-pseudo.png index 6c5ee67fa..8a13aadb2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-pseudo.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPad-pseudo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:180b69501525210102f696b7d7e7c6030070b2fce796149040a8310758cd826a -size 153988 +oid sha256:9704b5b3af36640a459086aeac5732b7308a293555f2a8227c4f8bf6033ec9ea +size 153135 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-en-GB.png index a8dda4099..f64677d65 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-en-GB.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-en-GB.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:525db300c8ddf0b4277f082d972338bbcddef87ccc12c72b615ed8dfce8dc367 -size 89218 +oid sha256:9780f6394e4a459137e7357ecf520fd193714d3e091258f63ccbf73522787034 +size 90779 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-pseudo.png index e5f01260a..8541b2296 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-pseudo.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.Managing-iPhone-pseudo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df0e19c0abbd1b39e399f3b8f7d033fdf5bf8c5ce688688027fc7ed856e78d04 -size 97285 +oid sha256:830f150bed0d92a729e47ad6ac263c68178b179de8955a25a4aac3c05126e1b2 +size 96788 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-en-GB-0.png index 684887eda..e1662ae71 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9396e9b4d4be5286a09b62fda56aae69c1ea862cad78f196151f3c47a2b2429e -size 233895 +oid sha256:82d4bd888ba03059dd94297a561b4b53d6584a8e10f5f81a6197370898c85d6e +size 234307 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png index 8749fac76..c7c988d4f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd3560a4acae0e9f1e635343f0f4a5b46ebc55b9853e93c59233457948cdfe33 -size 263863 +oid sha256:76b3679937eb3ff7e92c4cce0d654fa9895dba93dc228d9f1c9165e040d51d14 +size 264529 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-en-GB-0.png index 9fcc3eeac..4d853ae18 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df56484cef6939240050513ca42a0d29b843b5a3362b292fc3d5d8ed14076ddb -size 175828 +oid sha256:8f8c4c4e33ce89bd6a25a40db74f149b18b3994aae8513b1fd10fe24859dfda6 +size 176522 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-pseudo-0.png index 315ecdb34..cb8fbb8b6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08b11c147ca9ac8b855af225fdea4f606261b9ad8d0af4043a231666a006c96a -size 197580 +oid sha256:37f0f4765abc7592e0e890fdd214bfac8be5003067f773687be992b9a96b37da +size 198295 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-en-GB-0.png index dcfcb02e3..fc6f76fb0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da8634792cdf250fc915387d74a513e71375e4fde05fde2260618eee8bd705c3 -size 127480 +oid sha256:15f22091f345610f1dfd613684f2ee4ada908d4ca2c862327f4b96ff2f9f3013 +size 127224 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-pseudo-0.png index be9c1373c..93dbc5fd6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spacesScreen.iPhone-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af7a804c1ab88187c5df2a1b3bca2161ec4afe05c7f013763cbb1dd70b1a2b3b -size 150444 +oid sha256:f043cc81549b07df4b489d52b35aa1ac8b3136ebec006adb6ce69e6bc8d53b06 +size 150115 diff --git a/UnitTests/Sources/SpaceAddRoomsScreenViewModelTests.swift b/UnitTests/Sources/SpaceAddRoomsScreenViewModelTests.swift index 0301ab78a..c8b2a350c 100644 --- a/UnitTests/Sources/SpaceAddRoomsScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceAddRoomsScreenViewModelTests.swift @@ -13,6 +13,8 @@ import XCTest @MainActor class SpaceAddRoomsScreenViewModelTests: XCTestCase { + var spaceRoomListProxy: SpaceRoomListProxyMock! + var viewModel: SpaceAddRoomsScreenViewModelProtocol! var context: SpaceAddRoomsScreenViewModelType.Context { viewModel.context } @@ -41,11 +43,13 @@ class SpaceAddRoomsScreenViewModelTests: XCTestCase { context.send(viewAction: .save) try await deferredAction.fulfill() + + XCTAssertTrue(spaceRoomListProxy.resetCalled, "The room list should be reset to pick up the changes.") } func setupViewModel() { let summaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))) - let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(isSpace: true)))) + spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(isSpace: true)))) let clientProxy = ClientProxyMock(.init()) clientProxy.recentlyVisitedRoomsFilterReturnValue = .init(repeating: JoinedRoomProxyMock(.init()), count: 5) diff --git a/UnitTests/Sources/SpaceScreenViewModelTests.swift b/UnitTests/Sources/SpaceScreenViewModelTests.swift index f0934c99d..17f60030e 100644 --- a/UnitTests/Sources/SpaceScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceScreenViewModelTests.swift @@ -234,6 +234,7 @@ class SpaceScreenViewModelTests: XCTestCase { XCTAssertTrue(context.viewState.visibleRooms.contains { $0.isSpace }, "Confirming should restore the hidden spaces when done.") XCTAssertEqual(spaceServiceProxy.removeChildFromCallsCount, 2, "Each selected room should have been removed.") + XCTAssertTrue(spaceRoomListProxy.resetCalled, "The room list should be reset to pick up the changes.") } func testLeavingSpace() async throws { diff --git a/project.yml b/project.yml index 827b8e826..a4a274eb1 100644 --- a/project.yml +++ b/project.yml @@ -73,7 +73,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 26.1.13 + exactVersion: 26.01.20-2 # path: ../matrix-rust-sdk Compound: path: compound-ios