diff --git a/ElementX/Sources/FlowCoordinators/SpaceExplorerFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceExplorerFlowCoordinator.swift index 14ab705f9..802408fc8 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceExplorerFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceExplorerFlowCoordinator.swift @@ -9,8 +9,10 @@ import Combine import Foundation import SwiftState -enum SpaceExplorerFlowCoordinatorAction: Equatable { +enum SpaceExplorerFlowCoordinatorAction { case showSettings + case presentCallScreen(roomProxy: JoinedRoomProxyProtocol) + case verifyUser(userID: String) } class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol { @@ -113,7 +115,7 @@ class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol { private func presentSpaceList() { let parameters = SpaceListScreenCoordinatorParameters(userSession: userSession, - selectedSpaceSubject: selectedSpaceSubject.asCurrentValuePublisher(), + selectedSpacePublisher: selectedSpaceSubject.asCurrentValuePublisher(), userIndicatorController: flowParameters.userIndicatorController) let coordinator = SpaceListScreenCoordinator(parameters: parameters) coordinator.actionsPublisher @@ -143,6 +145,10 @@ class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { + case .presentCallScreen(let roomProxy): + actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) + case .verifyUser(let userID): + actionsSubject.send(.verifyUser(userID: userID)) case .finished: stateMachine.tryEvent(.deselectSpace) } diff --git a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift index 7fa43f288..a60aa0093 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift @@ -9,7 +9,9 @@ import Combine import Foundation import SwiftState -enum SpaceFlowCoordinatorAction: Equatable { +enum SpaceFlowCoordinatorAction { + case presentCallScreen(roomProxy: JoinedRoomProxyProtocol) + case verifyUser(userID: String) case finished } @@ -20,17 +22,22 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { private let navigationStackCoordinator: NavigationStackCoordinator - private var childSpaceFlowCoordinator: SpaceFlowCoordinator? - private let flowParameters: CommonFlowParameters + private let selectedSpaceRoomSubject: CurrentValueSubject = .init(nil) + + private var childSpaceFlowCoordinator: SpaceFlowCoordinator? + private var roomFlowCoordinator: RoomFlowCoordinator? + indirect enum State: StateType { /// The state machine hasn't started. case initial /// The root screen for this flow. case space - /// A child flow is in progress. + /// A child (space) flow is in progress. case presentingChild(childSpaceID: String, previousState: State) + /// A room flow is in progress + case roomFlow(previousState: State) } enum Event: EventType { @@ -43,6 +50,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { case startChildFlow /// Tidy-up the child flow after it has dismissed itself. case stopChildFlow + + case startRoomFlow(roomID: String) + case stopRoomFlow } private let stateMachine: StateMachine @@ -91,6 +101,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { case .presentingChild: childSpaceFlowCoordinator?.clearRoute(animated: animated) clearRoute(animated: animated) // Re-run with the state machine back in the .space state. + case .roomFlow: + roomFlowCoordinator?.clearRoute(animated: animated) + clearRoute(animated: animated) // Re-run with the state machine back in the .space state. } } @@ -116,6 +129,24 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { } handler: { [weak self] _ in guard let self else { return } childSpaceFlowCoordinator = nil + selectedSpaceRoomSubject.send(nil) + } + + stateMachine.addRouteMapping { event, fromState, _ in + guard case .startRoomFlow = event, case .space = fromState else { return nil } + return .roomFlow(previousState: fromState) + } handler: { [weak self] context in + guard let self, case let .startRoomFlow(roomID) = context.event else { return } + startRoomFlow(roomID: roomID) + } + + stateMachine.addRouteMapping { event, fromState, _ in + guard event == .stopRoomFlow, case let .roomFlow(previousState) = fromState else { return nil } + return previousState + } handler: { [weak self] _ in + guard let self else { return } + roomFlowCoordinator = nil + selectedSpaceRoomSubject.send(nil) } stateMachine.addErrorHandler { context in @@ -126,6 +157,7 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { private func presentSpace() { let parameters = SpaceScreenCoordinatorParameters(spaceRoomListProxy: spaceRoomListProxy, spaceServiceProxy: spaceServiceProxy, + selectedSpaceRoomPublisher: selectedSpaceRoomSubject.asCurrentValuePublisher(), mediaProvider: flowParameters.userSession.mediaProvider, userIndicatorController: flowParameters.userIndicatorController) let coordinator = SpaceScreenCoordinator(parameters: parameters) @@ -135,6 +167,8 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { switch action { case .selectSpace(let spaceRoomListProxy): stateMachine.tryEvent(.startChildFlow, userInfo: spaceRoomListProxy) + case .selectRoom(let roomID): + stateMachine.tryEvent(.startRoomFlow(roomID: roomID)) } } .store(in: &cancellables) @@ -164,6 +198,10 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { + case .presentCallScreen(let roomProxy): + actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) + case .verifyUser(let userID): + actionsSubject.send(.verifyUser(userID: userID)) case .finished: stateMachine.tryEvent(.stopChildFlow) } @@ -172,5 +210,31 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { childSpaceFlowCoordinator = coordinator coordinator.start() + selectedSpaceRoomSubject.send(spaceRoomListProxy.spaceRoomProxy.id) + } + + private func startRoomFlow(roomID: String) { + let coordinator = RoomFlowCoordinator(roomID: roomID, + isChildFlow: true, + navigationStackCoordinator: navigationStackCoordinator, + flowParameters: flowParameters) + coordinator.actions + .sink { [weak self] action in + guard let self else { return } + + switch action { + case .presentCallScreen(let roomProxy): + actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) + case .verifyUser(let userID): + actionsSubject.send(.verifyUser(userID: userID)) + case .finished: + stateMachine.tryEvent(.stopRoomFlow) + } + } + .store(in: &cancellables) + + roomFlowCoordinator = coordinator + coordinator.handleAppRoute(.room(roomID: roomID, via: []), animated: true) + selectedSpaceRoomSubject.send(roomID) } } diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 32087e997..9f16b6989 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -217,6 +217,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { .sink { [weak self] action in guard let self else { return } switch action { + case .presentCallScreen(let roomProxy): + presentCallScreen(roomProxy: roomProxy) + case .verifyUser(let userID): + presentSessionVerificationScreen(flow: .userInitiator(userID: userID)) case .showSettings: stateMachine.tryEvent(.showSettingsScreen) } diff --git a/ElementX/Sources/Mocks/ClientProxyMock.swift b/ElementX/Sources/Mocks/ClientProxyMock.swift index d209cc70f..0b2211c60 100644 --- a/ElementX/Sources/Mocks/ClientProxyMock.swift +++ b/ElementX/Sources/Mocks/ClientProxyMock.swift @@ -14,6 +14,7 @@ struct ClientProxyMockConfiguration { var userID: String = RoomMemberProxyMock.mockMe.userID var deviceID: String? var roomSummaryProvider: RoomSummaryProviderProtocol = RoomSummaryProviderMock(.init()) + var joinedSpaceRooms: [SpaceRoomProxyProtocol] = [] var roomDirectorySearchProxy: RoomDirectorySearchProxyProtocol? var recoveryState: SecureBackupRecoveryState = .enabled @@ -92,11 +93,13 @@ extension ClientProxyMock { spaceService = SpaceServiceProxyMock(.init()) roomForIdentifierClosure = { [weak self] identifier in - guard let room = self?.roomSummaryProvider.roomListPublisher.value.first(where: { $0.id == identifier }) else { - return nil + if let room = self?.roomSummaryProvider.roomListPublisher.value.first(where: { $0.id == identifier }) { + await .joined(JoinedRoomProxyMock(.init(id: room.id, name: room.name))) + } else if let spaceRoom = configuration.joinedSpaceRooms.first(where: { $0.id == identifier }) { + await .joined(JoinedRoomProxyMock(.init(id: spaceRoom.id, name: spaceRoom.name))) + } else { + nil } - - return await .joined(JoinedRoomProxyMock(.init(id: room.id, name: room.name))) } userIdentityForReturnValue = .success(UserIdentityProxyMock(configuration: .init())) diff --git a/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift b/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift index 8faaa1a49..7c39c9b3c 100644 --- a/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift @@ -104,7 +104,8 @@ extension [SpaceRoomProxyProtocol] { name: "Management", isSpace: false, joinedMembersCount: 12, - topic: "This is where everything gets organised 📋."))] + topic: "This is where everything gets organised 📋.", + state: .joined))] } private static func makeSpaceRooms(isSpace: Bool) -> [SpaceRoomProxyMock] { diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenCoordinator.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenCoordinator.swift index 5beadfa4d..878d52e43 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenCoordinator.swift @@ -12,7 +12,7 @@ import SwiftUI struct SpaceListScreenCoordinatorParameters { let userSession: UserSessionProtocol - let selectedSpaceSubject: CurrentValuePublisher + let selectedSpacePublisher: CurrentValuePublisher let userIndicatorController: UserIndicatorControllerProtocol } @@ -36,7 +36,7 @@ final class SpaceListScreenCoordinator: CoordinatorProtocol { self.parameters = parameters viewModel = SpaceListScreenViewModel(userSession: parameters.userSession, - selectedSpaceSubject: parameters.selectedSpaceSubject, + selectedSpacePublisher: parameters.selectedSpacePublisher, userIndicatorController: parameters.userIndicatorController) } diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift index f072f4cb0..74806716f 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift @@ -20,7 +20,7 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie } init(userSession: UserSessionProtocol, - selectedSpaceSubject: CurrentValuePublisher, + selectedSpacePublisher: CurrentValuePublisher, userIndicatorController: UserIndicatorControllerProtocol) { spaceServiceProxy = userSession.clientProxy.spaceService self.userIndicatorController = userIndicatorController @@ -35,7 +35,7 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie .weakAssign(to: \.state.joinedSpaces, on: self) .store(in: &cancellables) - selectedSpaceSubject + selectedSpacePublisher .weakAssign(to: \.state.selectedSpaceID, on: self) .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift index c01f9b757..ac5425c25 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift @@ -107,7 +107,7 @@ struct SpaceListScreen_Previews: PreviewProvider, TestablePreview { clientProxy.spaceService = SpaceServiceProxyMock(.init(joinedSpaces: .mockJoinedSpaces)) let viewModel = SpaceListScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)), - selectedSpaceSubject: .init(nil), + selectedSpacePublisher: .init(nil), userIndicatorController: UserIndicatorControllerMock()) return viewModel diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift index 711fc4d09..a1b1ea963 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift @@ -13,12 +13,14 @@ import SwiftUI struct SpaceScreenCoordinatorParameters { let spaceRoomListProxy: SpaceRoomListProxyProtocol let spaceServiceProxy: SpaceServiceProxyProtocol + let selectedSpaceRoomPublisher: CurrentValuePublisher let mediaProvider: MediaProviderProtocol let userIndicatorController: UserIndicatorControllerProtocol } enum SpaceScreenCoordinatorAction { case selectSpace(SpaceRoomListProxyProtocol) + case selectRoom(roomID: String) } final class SpaceScreenCoordinator: CoordinatorProtocol { @@ -37,6 +39,7 @@ final class SpaceScreenCoordinator: CoordinatorProtocol { viewModel = SpaceScreenViewModel(spaceRoomListProxy: parameters.spaceRoomListProxy, spaceServiceProxy: parameters.spaceServiceProxy, + selectedSpaceRoomPublisher: parameters.selectedSpaceRoomPublisher, mediaProvider: parameters.mediaProvider, userIndicatorController: parameters.userIndicatorController) } @@ -49,6 +52,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol { switch action { case .selectSpace(let spaceRoomListProxy): actionsSubject.send(.selectSpace(spaceRoomListProxy)) + case .selectRoom(let roomID): + actionsSubject.send(.selectRoom(roomID: roomID)) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift index bb6fee4ce..24e4c1d58 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift @@ -9,6 +9,7 @@ import Foundation enum SpaceScreenViewModelAction { case selectSpace(SpaceRoomListProxyProtocol) + case selectRoom(roomID: String) } struct SpaceScreenViewState: BindableState { @@ -16,8 +17,11 @@ struct SpaceScreenViewState: BindableState { var isPaginating = false var rooms: [SpaceRoomProxyProtocol] + var selectedSpaceRoomID: String? var bindings = SpaceScreenViewStateBindings() + + var spaceName: String { space.name ?? L10n.commonSpace } } struct SpaceScreenViewStateBindings { } diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift index 19dc0d7fb..45500fba4 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift @@ -21,13 +21,15 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc init(spaceRoomListProxy: SpaceRoomListProxyProtocol, spaceServiceProxy: SpaceServiceProxyProtocol, + selectedSpaceRoomPublisher: CurrentValuePublisher, mediaProvider: MediaProviderProtocol, userIndicatorController: UserIndicatorControllerProtocol) { self.spaceServiceProxy = spaceServiceProxy self.userIndicatorController = userIndicatorController super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceRoomProxy, - rooms: spaceRoomListProxy.spaceRoomsPublisher.value), + rooms: spaceRoomListProxy.spaceRoomsPublisher.value, + selectedSpaceRoomID: selectedSpaceRoomPublisher.value), mediaProvider: mediaProvider) spaceRoomListProxy.spaceRoomsPublisher @@ -50,6 +52,10 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc } } .store(in: &cancellables) + + selectedSpaceRoomPublisher + .weakAssign(to: \.state.selectedSpaceRoomID, on: self) + .store(in: &cancellables) } // MARK: - Public @@ -61,8 +67,10 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc case .spaceAction(.select(let spaceRoomProxy)): if spaceRoomProxy.isSpace { Task { await selectSpace(spaceRoomProxy) } - } else { - #warning("Implement room flow") + } else if spaceRoomProxy.state == .joined { + // This probably doesn't need the state condition as the room flow will show a join screen, + // but we can allow this later, once we've updated the design to indicate the parent space. + actionsSubject.send(.selectRoom(roomID: spaceRoomProxy.id)) } case .spaceAction(.join(let spaceID)): #warning("Implement joining.") diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift index 33dd99f21..e3a87aa2c 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift @@ -19,16 +19,17 @@ struct SpaceScreen: View { rooms } } - .navigationTitle(context.viewState.space.name ?? L10n.commonSpace) - .navigationBarTitleDisplayMode(.inline) .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) + .navigationTitle(context.viewState.spaceName) + .navigationBarTitleDisplayMode(.inline) + .toolbar { toolbar } } @ViewBuilder var rooms: some View { ForEach(context.viewState.rooms, id: \.id) { spaceRoomProxy in SpaceRoomCell(spaceRoomProxy: spaceRoomProxy, - isSelected: false, + isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceRoomID, mediaProvider: context.mediaProvider) { action in context.send(viewAction: .spaceAction(action)) } @@ -39,6 +40,16 @@ struct SpaceScreen: View { .padding() } } + + var toolbar: some ToolbarContent { + // Use the same trick as the RoomScreen for a leading title view that + // also hides the navigation title. + ToolbarItem(placement: .principal) { + RoomHeaderView(roomName: context.viewState.spaceName, + roomAvatar: context.viewState.space.avatar, + mediaProvider: context.mediaProvider) + } + } } // MARK: - Previews @@ -66,6 +77,7 @@ struct SpaceScreen_Previews: PreviewProvider, TestablePreview { let viewModel = SpaceScreenViewModel(spaceRoomListProxy: spaceRoomListProxy, spaceServiceProxy: SpaceServiceProxyMock(.init()), + selectedSpaceRoomPublisher: .init(nil), mediaProvider: MediaProviderMock(configuration: .init()), userIndicatorController: UserIndicatorControllerMock()) return viewModel diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 7ec505cae..12b487ab8 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -571,7 +571,10 @@ class MockScreen: Identifiable { appSettings.analyticsConsentState = .optedOut appSettings.spacesEnabled = true - let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", deviceID: "MOCKCLIENT", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) + let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", + deviceID: "MOCKCLIENT", + roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), + joinedSpaceRooms: .mockSingleRoom)) // The tab bar remains hidden for the non-spaces tests as we don't supply any mock spaces. let spaceServiceProxy = SpaceServiceProxyMock(id == .userSessionSpacesFlow ? .populated : .init()) 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 2089680a0..be07f3192 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:8a9a4c1899fffb9c101f87eeeb2413c962f72daddb2bdf10b23c1aa8267a6707 -size 241775 +oid sha256:aa43fefcbe0406d7c84752152b5f4ad6951175fcc98a9fb48b0f6cad24d0f012 +size 242481 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPad-pseudo-0.png index 0e6484a66..83e5b74c5 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:4debd3d362dfdcec1eebbade1159b3cbbafad46e2daacb1511ad2d08c847926e -size 279363 +oid sha256:949fa7494236c24c00438329892fb75750eb08b310bf1c4e56e918e8a68feec4 +size 280034 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-en-GB-0.png index 9ce6057d1..5010a6c09 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1cac5e788e68553c910fcf9d10213c025c593763e72e448db359b2a50f06bd0 -size 186591 +oid sha256:80f8c4e7b7c90e6f6ef159c7642aaed70f93f4788686d39e6518f20b98e7f5ab +size 187209 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-pseudo-0.png index c23ebafa5..9823ff0a4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/spaceScreen.iPhone-16-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90a7af41076c73f8fc3671d6402bdc9e93e23ea592c7efa6647242c44541a900 -size 206847 +oid sha256:75524c40db1a8c622b3a37cde5ac93c022b44f807e5d18b986b906fe6e47d2e8 +size 207423 diff --git a/UITests/Sources/UserSessionScreenTests.swift b/UITests/Sources/UserSessionScreenTests.swift index 983ace1fc..a68fdd736 100644 --- a/UITests/Sources/UserSessionScreenTests.swift +++ b/UITests/Sources/UserSessionScreenTests.swift @@ -12,6 +12,7 @@ class UserSessionScreenTests: XCTestCase { let firstRoomName = "Foundation 🔭🪐🌌" let firstSpaceName = "The Foundation" let firstSubspaceName = "Company Space" + let firstSubspaceRoomName = "Management" enum Step { static let homeScreen = 1 @@ -21,6 +22,7 @@ class UserSessionScreenTests: XCTestCase { static let spaceList = 5 static let spaceScreen = 6 static let subspaceScreen = 7 + static let subspaceRoomScreen = 8 } func testUserSessionFlows() async throws { @@ -69,6 +71,8 @@ class UserSessionScreenTests: XCTestCase { func testSpaceExploration() async throws { let app = Application.launch(.userSessionSpacesFlow) + app.swipeDown() // Make sure the header shows a large title + try await app.assertScreenshot(step: Step.spacesTabBar) // app.tabBars doesn't work on iPadOS 18 😐 @@ -85,5 +89,10 @@ class UserSessionScreenTests: XCTestCase { XCTAssert(app.staticTexts[firstSubspaceName].waitForExistence(timeout: 5.0)) try await Task.sleep(for: .seconds(1)) try await app.assertScreenshot(step: Step.subspaceScreen) + + app.buttons[A11yIdentifiers.spaceListScreen.spaceRoomName(firstSubspaceRoomName)].tap() + XCTAssert(app.staticTexts[firstSubspaceRoomName].waitForExistence(timeout: 5.0)) + try await Task.sleep(for: .seconds(1)) + try await app.assertScreenshot(step: Step.subspaceRoomScreen) } } diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-4.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-4.png index cd7df060f..52d80cd87 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-4.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-4.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dee57958e736136e2598db20aae58486bf68d56352c68097319e3f4e2cea6dd9 -size 452748 +oid sha256:ccfe2cd51a3d032410862ded6a179f8cf4987f9c27ad7cdfaa4c0a2748c3b1f5 +size 452759 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-6.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-6.png index 6e8253e4f..ea701cfc4 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-6.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-6.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63044eae82b5caf0e61eaa7e65f2fff30e2dca8fe282ce7c7fd2e4edd562811d -size 373691 +oid sha256:22815607d190c5027b125360a511384eccbc8c997516e0a349d38b316d37502d +size 374015 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-7.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-7.png index b925c17fa..2131ec32a 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-7.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-7.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d16db9f4d2cab604bc19a76585202586df21749d48da09c8e969c2624637ccf -size 277095 +oid sha256:ef257a3d7f03a0eaee4e4354c847c90cbc9d0f9d5c52767d1d49d200232337b0 +size 274101 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-8.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-8.png new file mode 100644 index 000000000..f249fb2b0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPad-18-5-en-GB-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b71980e1f2646b261902d4ba50240ee92c99d7e6287a3392ccfbaaf074a20ace +size 477038 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-4.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-4.png index 4539d353d..c93cdf317 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-4.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-4.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f3668e91005046ed8ee295d34c4f160a1501e427337c6bf96cdcdf34aa83c65 -size 484663 +oid sha256:01ef09ce91a3b76182fdf9ea27ac181d5a1584f5dac6b2826d7fc00cfdbbc86d +size 509366 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-6.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-6.png index a7a4ede5d..839bf8e01 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-6.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-6.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d966e5361b6c386668228ee436c1fbf4a2b53065169120aaca669ac485736c5f -size 402376 +oid sha256:cd6229bda0aba7184a460f5156157f13a09d346688ea1cb3b252584919e6b3d5 +size 293006 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-7.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-7.png index d0757933f..42bf3c92f 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-7.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-7.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10c0b735d009691762e8719ff2dc3c01ce8e1c984e080caebe322336a6d378bd -size 117024 +oid sha256:869be3a8f6ed1705de9fa6d37b6ce0a2e143a6f53a5b439f7cf67e93cf2d082f +size 109237 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-8.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-8.png new file mode 100644 index 000000000..b3547a043 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen.testSpaceExploration-iPhone-18-5-en-GB-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a62d21a23c9c6bdfeb73fbe24cff464aaf41d9b0252ec68130788ca660f2de9 +size 324914 diff --git a/UnitTests/Sources/SpaceListScreenViewModelTests.swift b/UnitTests/Sources/SpaceListScreenViewModelTests.swift index e3e3fb36d..1632ba217 100644 --- a/UnitTests/Sources/SpaceListScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceListScreenViewModelTests.swift @@ -76,7 +76,7 @@ class SpaceListScreenViewModelTests: XCTestCase { clientProxy.spaceService = spaceServiceProxy viewModel = SpaceListScreenViewModel(userSession: userSession, - selectedSpaceSubject: .init(nil), + selectedSpacePublisher: .init(nil), userIndicatorController: UserIndicatorControllerMock()) } } diff --git a/UnitTests/Sources/SpaceScreenViewModelTests.swift b/UnitTests/Sources/SpaceScreenViewModelTests.swift index 8e8e08db9..980436fba 100644 --- a/UnitTests/Sources/SpaceScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceScreenViewModelTests.swift @@ -117,6 +117,7 @@ class SpaceScreenViewModelTests: XCTestCase { viewModel = SpaceScreenViewModel(spaceRoomListProxy: spaceRoomListProxy, spaceServiceProxy: spaceServiceProxy, + selectedSpaceRoomPublisher: .init(nil), mediaProvider: MediaProviderMock(configuration: .init()), userIndicatorController: UserIndicatorControllerMock()) }