diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index ea998c32d..2bc5d599d 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -273,6 +273,19 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // early return above could result in trying to access the room's timeline provider // before it has been set which triggers a fatal error. self.roomProxy = roomProxy + + // Subscribe to room info updates in order to detect rooms being left on other devices + // and react accordingly by dismissing this flow coordinator. + self.roomProxy.infoPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] info in + guard let self else { return } + + if info.membership == .left || info.membership == .banned, stateMachine.state != .complete { + stateMachine.tryEvent(.dismissFlow) + } + } + .store(in: &cancellables) } // swiftlint:disable:next function_body_length diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index 0d574662a..126d569c3 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -43,7 +43,10 @@ struct JoinedRoomProxyMockConfiguration { var canUserPin = true var shouldUseAutoUpdatingTimeline = false + var joinRule: JoinRule? + var membership: Membership = .joined + var isVisibleInPublicDirectory = false } @@ -151,7 +154,7 @@ extension RoomInfo { isFavourite: false, canonicalAlias: configuration.canonicalAlias, alternativeAliases: configuration.alternativeAliases, - membership: .joined, + membership: configuration.membership, inviter: configuration.inviter.map { RoomMember(userId: $0.userID, displayName: $0.displayName, avatarUrl: $0.avatarURL?.absoluteString, diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index dc6e3293b..6140b0cda 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -268,6 +268,31 @@ class RoomFlowCoordinatorTests: XCTestCase { XCTAssertNil(navigationStackCoordinator.sheetCoordinator, "The media upload sheet shouldn't be shown when sharing text.") } + func testLeavingRoom() async throws { + await setupRoomFlowCoordinator() + + var configuration = JoinedRoomProxyMockConfiguration() + let roomProxy = JoinedRoomProxyMock(configuration) + + let roomInfoSubject = CurrentValueSubject(.init(roomInfo: .init(configuration))) + roomProxy.infoPublisher = roomInfoSubject.asCurrentValuePublisher() + + clientProxy.roomForIdentifierClosure = { _ in + .joined(roomProxy) + } + + try await process(route: .room(roomID: "1", via: [])) + + let fulfillment = deferFulfillment(roomFlowCoordinator.actions) { action in + action == .finished + } + + configuration.membership = .left + roomInfoSubject.send(.init(roomInfo: .init(configuration))) + + try await fulfillment.fulfill() + } + // MARK: - Private private func process(route: AppRoute) async throws {