mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Accept space invites from a home screen cell. (#4554)
* Push the SpaceScreen after accepting an invite from the room list. * Add a test for accepting a space invite.
This commit is contained in:
@@ -29,6 +29,8 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var roomFlowCoordinator: RoomFlowCoordinator?
|
||||
// periphery:ignore - retaining purpose
|
||||
private var spaceFlowCoordinator: SpaceFlowCoordinator?
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
|
||||
@@ -117,7 +119,7 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
|
||||
case .roomDetails(let roomID):
|
||||
if stateMachine.state.roomListSelectedRoomID == roomID {
|
||||
if case .room(roomID) = stateMachine.state.detailState {
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .roomDetails), userInfo: .init(animated: animated))
|
||||
@@ -154,7 +156,7 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.processEvent(.showShareExtensionRoomList(sharePayload: payload), userInfo: .init(animated: animated))
|
||||
}
|
||||
case .transferOwnership(let roomID):
|
||||
if stateMachine.state.roomListSelectedRoomID == roomID {
|
||||
if case .room(roomID) = stateMachine.state.detailState {
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .transferOwnership))
|
||||
@@ -178,12 +180,15 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private func setupStateMachine() {
|
||||
stateMachine.addTransitionHandler { [weak self] context in
|
||||
guard let self else { return }
|
||||
let animated = (context.userInfo as? ChatsFlowCoordinatorStateMachine.EventUserInfo)?.animated ?? true
|
||||
|
||||
let userInfo = context.userInfo as? ChatsFlowCoordinatorStateMachine.EventUserInfo
|
||||
let animated = userInfo?.animated ?? true
|
||||
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (.initial, .start, .roomList):
|
||||
presentHomeScreen()
|
||||
case(.roomList(let roomListSelectedRoomID), .selectRoom(let roomID, let via, let entryPoint), .roomList):
|
||||
if roomListSelectedRoomID == roomID,
|
||||
case(.roomList(let detailState), .selectRoom(let roomID, let via, let entryPoint), .roomList):
|
||||
if case .room(roomID) = detailState,
|
||||
!entryPoint.isEventID, // Don't reuse the existing room so the live timeline is hidden while the detached timeline is loading.
|
||||
let roomFlowCoordinator {
|
||||
let route: AppRoute = switch entryPoint {
|
||||
@@ -195,11 +200,20 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
roomFlowCoordinator.handleAppRoute(route, animated: animated)
|
||||
} else {
|
||||
if case .space = detailState {
|
||||
dismissRoomFlow(animated: animated)
|
||||
}
|
||||
startRoomFlow(roomID: roomID, via: via, entryPoint: entryPoint, animated: animated)
|
||||
}
|
||||
actionsSubject.send(.hideCallScreenOverlay) // Turn any active call into a PiP so that navigation from a notification is visible to the user.
|
||||
case(.roomList, .deselectRoom, .roomList):
|
||||
dismissRoomFlow(animated: animated)
|
||||
|
||||
case(.roomList, .startSpaceFlow, .roomList):
|
||||
guard let spaceRoomListProxy = userInfo?.spaceRoomListProxy else { fatalError("A space room list proxy is required.") }
|
||||
startSpaceFlow(spaceRoomListProxy: spaceRoomListProxy, animated: animated)
|
||||
case (.roomList, .finishedSpaceFlow, .roomList):
|
||||
dismissSpaceFlow(animated: animated)
|
||||
|
||||
case (.roomList, .feedbackScreen, .feedbackScreen):
|
||||
bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .sheet(sidebarNavigationStackCoordinator),
|
||||
@@ -264,8 +278,8 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
stateMachine.addTransitionHandler { [weak self] context in
|
||||
switch context.toState {
|
||||
case .roomList(let roomListSelectedRoomID):
|
||||
self?.selectedRoomSubject.send(roomListSelectedRoomID)
|
||||
case .roomList(detailState: .room(let detailStateRoomID)):
|
||||
self?.selectedRoomSubject.send(detailStateRoomID)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -351,9 +365,11 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
handleAppRoute(.roomDetails(roomID: roomID), animated: true)
|
||||
case .presentReportRoom(let roomID):
|
||||
stateMachine.processEvent(.presentReportRoomScreen(roomID: roomID))
|
||||
case .presentSpace(let spaceRoomListProxy):
|
||||
stateMachine.processEvent(.startSpaceFlow, userInfo: .init(animated: true, spaceRoomListProxy: spaceRoomListProxy))
|
||||
case .roomLeft(let roomID):
|
||||
if case .roomList(roomListSelectedRoomID: let roomListSelectedRoomID) = stateMachine.state,
|
||||
roomListSelectedRoomID == roomID {
|
||||
if case .roomList(detailState: .room(let detailStateRoomID)) = stateMachine.state,
|
||||
detailStateRoomID == roomID {
|
||||
clearRoute(animated: true)
|
||||
}
|
||||
case .presentSettingsScreen:
|
||||
@@ -398,8 +414,8 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch action {
|
||||
case .dismiss(let shouldLeaveRoom):
|
||||
if shouldLeaveRoom,
|
||||
case .roomList(let roomListSelectedRoomID) = stateMachine.state,
|
||||
roomListSelectedRoomID == roomID {
|
||||
case .roomList(detailState: .room(let detailStateRoomID)) = stateMachine.state,
|
||||
detailStateRoomID == roomID {
|
||||
clearRoute(animated: true)
|
||||
}
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
@@ -491,6 +507,43 @@ class ChatsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
roomFlowCoordinator = nil
|
||||
}
|
||||
|
||||
// MARK: Space Flow
|
||||
|
||||
private func startSpaceFlow(spaceRoomListProxy: SpaceRoomListProxyProtocol, animated: Bool) {
|
||||
let coordinator = SpaceFlowCoordinator(entryPoint: .space(spaceRoomListProxy),
|
||||
spaceServiceProxy: userSession.clientProxy.spaceService,
|
||||
isChildFlow: false,
|
||||
navigationStackCoordinator: detailNavigationStackCoordinator,
|
||||
flowParameters: flowParameters)
|
||||
coordinator.actionsPublisher
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .presentCallScreen(let roomProxy):
|
||||
actionsSubject.send(.showCallScreen(roomProxy: roomProxy))
|
||||
case .verifyUser(let userID):
|
||||
actionsSubject.send(.sessionVerification(.userInitiator(userID: userID)))
|
||||
case .finished:
|
||||
stateMachine.processEvent(.finishedSpaceFlow)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
spaceFlowCoordinator = coordinator
|
||||
|
||||
if navigationSplitCoordinator.detailCoordinator !== detailNavigationStackCoordinator {
|
||||
navigationSplitCoordinator.setDetailCoordinator(detailNavigationStackCoordinator, animated: animated)
|
||||
}
|
||||
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func dismissSpaceFlow(animated: Bool) {
|
||||
// Based on dismissRoomFlow, past me was very insistent that this must happen after the flow has tidied the stack 😅.
|
||||
navigationSplitCoordinator.setDetailCoordinator(nil, animated: animated)
|
||||
roomFlowCoordinator = nil
|
||||
}
|
||||
|
||||
// MARK: Start Chat
|
||||
|
||||
private func presentStartChat(animated: Bool) {
|
||||
|
||||
@@ -10,63 +10,69 @@ import Foundation
|
||||
import SwiftState
|
||||
|
||||
class ChatsFlowCoordinatorStateMachine {
|
||||
enum DetailState: Hashable {
|
||||
case room(roomID: String)
|
||||
case space
|
||||
}
|
||||
|
||||
/// States the AppCoordinator can find itself in
|
||||
enum State: StateType {
|
||||
/// The initial state, used before the coordinator starts
|
||||
case initial
|
||||
|
||||
/// Showing the home screen. The `roomListSelectedRoomID` represents the timeline shown on the detail panel (if any)
|
||||
case roomList(roomListSelectedRoomID: String?)
|
||||
case roomList(detailState: DetailState?)
|
||||
|
||||
/// Showing the feedback screen.
|
||||
case feedbackScreen(roomListSelectedRoomID: String?)
|
||||
case feedbackScreen(detailState: DetailState?)
|
||||
|
||||
/// Showing the recovery key screen.
|
||||
case recoveryKeyScreen(roomListSelectedRoomID: String?)
|
||||
case recoveryKeyScreen(detailState: DetailState?)
|
||||
|
||||
/// Showing the encryption reset flow.
|
||||
case encryptionResetFlow(roomListSelectedRoomID: String?)
|
||||
case encryptionResetFlow(detailState: DetailState?)
|
||||
|
||||
/// Showing the start chat screen
|
||||
case startChatScreen(roomListSelectedRoomID: String?)
|
||||
case startChatScreen(detailState: DetailState?)
|
||||
|
||||
/// Showing the logout flows
|
||||
case logoutConfirmationScreen(roomListSelectedRoomID: String?)
|
||||
case logoutConfirmationScreen(detailState: DetailState?)
|
||||
|
||||
/// Showing Room Directory Search screen
|
||||
case roomDirectorySearchScreen(roomListSelectedRoomID: String?)
|
||||
case roomDirectorySearchScreen(detailState: DetailState?)
|
||||
|
||||
/// Showing the user profile screen. This screen clears the navigation.
|
||||
case userProfileScreen
|
||||
|
||||
/// Showing the report room screen, for the given room identrifier
|
||||
case reportRoomScreen(roomListSelectedRoomID: String?)
|
||||
case reportRoomScreen(detailState: DetailState?)
|
||||
|
||||
case shareExtensionRoomList(sharePayload: ShareExtensionPayload)
|
||||
|
||||
case declineAndBlockUserScreen(roomListSelectedRoomID: String?)
|
||||
case declineAndBlockUserScreen(detailState: DetailState?)
|
||||
|
||||
/// The selected room ID from the state if available.
|
||||
var roomListSelectedRoomID: String? {
|
||||
var detailState: DetailState? {
|
||||
switch self {
|
||||
case .initial, .userProfileScreen, .shareExtensionRoomList:
|
||||
nil
|
||||
case .roomList(let roomListSelectedRoomID),
|
||||
.feedbackScreen(let roomListSelectedRoomID),
|
||||
.recoveryKeyScreen(let roomListSelectedRoomID),
|
||||
.encryptionResetFlow(let roomListSelectedRoomID),
|
||||
.startChatScreen(let roomListSelectedRoomID),
|
||||
.logoutConfirmationScreen(let roomListSelectedRoomID),
|
||||
.roomDirectorySearchScreen(let roomListSelectedRoomID),
|
||||
.reportRoomScreen(let roomListSelectedRoomID),
|
||||
.declineAndBlockUserScreen(let roomListSelectedRoomID):
|
||||
roomListSelectedRoomID
|
||||
case .roomList(let detailState),
|
||||
.feedbackScreen(let detailState),
|
||||
.recoveryKeyScreen(let detailState),
|
||||
.encryptionResetFlow(let detailState),
|
||||
.startChatScreen(let detailState),
|
||||
.logoutConfirmationScreen(let detailState),
|
||||
.roomDirectorySearchScreen(let detailState),
|
||||
.reportRoomScreen(let detailState),
|
||||
.declineAndBlockUserScreen(let detailState):
|
||||
detailState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EventUserInfo {
|
||||
let animated: Bool
|
||||
var spaceRoomListProxy: SpaceRoomListProxyProtocol?
|
||||
}
|
||||
|
||||
/// Events that can be triggered on the AppCoordinator state machine
|
||||
@@ -82,6 +88,13 @@ class ChatsFlowCoordinatorStateMachine {
|
||||
/// The room screen has been dismissed
|
||||
case deselectRoom
|
||||
|
||||
/// Request presentation of a space.
|
||||
///
|
||||
/// The space's `RoomListProxyProtocol` must be provided in the `EventUserInfo`.
|
||||
case startSpaceFlow
|
||||
/// The space has been dismissed.
|
||||
case finishedSpaceFlow
|
||||
|
||||
/// Request presentation of the feedback screen
|
||||
case feedbackScreen
|
||||
/// The feedback screen has been dismissed
|
||||
@@ -134,59 +147,64 @@ class ChatsFlowCoordinatorStateMachine {
|
||||
}
|
||||
|
||||
private func configure() {
|
||||
stateMachine.addRoutes(event: .start, transitions: [.initial => .roomList(roomListSelectedRoomID: nil)])
|
||||
stateMachine.addRoutes(event: .start, transitions: [.initial => .roomList(detailState: nil)])
|
||||
|
||||
stateMachine.addRouteMapping { event, fromState, _ in
|
||||
switch (fromState, event) {
|
||||
case (.roomList, .selectRoom(let roomID, _, _)):
|
||||
return .roomList(roomListSelectedRoomID: roomID)
|
||||
return .roomList(detailState: .room(roomID: roomID))
|
||||
case (.roomList, .deselectRoom):
|
||||
return .roomList(roomListSelectedRoomID: nil)
|
||||
return .roomList(detailState: nil)
|
||||
|
||||
case (.roomList, .startSpaceFlow):
|
||||
return .roomList(detailState: .space)
|
||||
case (.roomList, .finishedSpaceFlow):
|
||||
return .roomList(detailState: nil)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .feedbackScreen):
|
||||
return .feedbackScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.feedbackScreen(let roomListSelectedRoomID), .dismissedFeedbackScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .feedbackScreen):
|
||||
return .feedbackScreen(detailState: detailState)
|
||||
case (.feedbackScreen(let detailState), .dismissedFeedbackScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .showRecoveryKeyScreen):
|
||||
return .recoveryKeyScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.recoveryKeyScreen(let roomListSelectedRoomID), .dismissedRecoveryKeyScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .showRecoveryKeyScreen):
|
||||
return .recoveryKeyScreen(detailState: detailState)
|
||||
case (.recoveryKeyScreen(let detailState), .dismissedRecoveryKeyScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .startEncryptionResetFlow):
|
||||
return .encryptionResetFlow(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.encryptionResetFlow(let roomListSelectedRoomID), .finishedEncryptionResetFlow):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .startEncryptionResetFlow):
|
||||
return .encryptionResetFlow(detailState: detailState)
|
||||
case (.encryptionResetFlow(let detailState), .finishedEncryptionResetFlow):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .showStartChatScreen):
|
||||
return .startChatScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.startChatScreen(let roomListSelectedRoomID), .dismissedStartChatScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .showStartChatScreen):
|
||||
return .startChatScreen(detailState: detailState)
|
||||
case (.startChatScreen(let detailState), .dismissedStartChatScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .showRoomDirectorySearchScreen):
|
||||
return .roomDirectorySearchScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomDirectorySearchScreen(let roomListSelectedRoomID), .dismissedRoomDirectorySearchScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .showRoomDirectorySearchScreen):
|
||||
return .roomDirectorySearchScreen(detailState: detailState)
|
||||
case (.roomDirectorySearchScreen(let detailState), .dismissedRoomDirectorySearchScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case (_, .showUserProfileScreen):
|
||||
return .userProfileScreen
|
||||
case (.userProfileScreen, .dismissedUserProfileScreen):
|
||||
return .roomList(roomListSelectedRoomID: nil)
|
||||
return .roomList(detailState: nil)
|
||||
|
||||
case (.roomList, .showShareExtensionRoomList(let sharePayload)):
|
||||
return .shareExtensionRoomList(sharePayload: sharePayload)
|
||||
case (.shareExtensionRoomList, .dismissedShareExtensionRoomList):
|
||||
return .roomList(roomListSelectedRoomID: nil)
|
||||
return .roomList(detailState: nil)
|
||||
|
||||
case (.roomList(let roomListSelectedRoomID), .presentReportRoomScreen):
|
||||
return .reportRoomScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.reportRoomScreen(let roomListSelectedRoomID), .dismissedReportRoomScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.roomList(let detailState), .presentReportRoomScreen):
|
||||
return .reportRoomScreen(detailState: detailState)
|
||||
case (.reportRoomScreen(let detailState), .dismissedReportRoomScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
case(.roomList(let roomListSelectedRoomID), .presentDeclineAndBlockScreen):
|
||||
return .declineAndBlockUserScreen(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case (.declineAndBlockUserScreen(let roomListSelectedRoomID), .dismissedDeclineAndBlockScreen):
|
||||
return .roomList(roomListSelectedRoomID: roomListSelectedRoomID)
|
||||
case(.roomList(let detailState), .presentDeclineAndBlockScreen):
|
||||
return .declineAndBlockUserScreen(detailState: detailState)
|
||||
case (.declineAndBlockUserScreen(let detailState), .dismissedDeclineAndBlockScreen):
|
||||
return .roomList(detailState: detailState)
|
||||
|
||||
default:
|
||||
return nil
|
||||
@@ -221,8 +239,8 @@ class ChatsFlowCoordinatorStateMachine {
|
||||
/// Flag indicating the machine is displaying room screen with given room identifier
|
||||
func isDisplayingRoomScreen(withRoomID roomID: String) -> Bool {
|
||||
switch stateMachine.state {
|
||||
case .roomList(let roomListSelectedRoomID):
|
||||
return roomID == roomListSelectedRoomID
|
||||
case .roomList(detailState: .room(let detailStateRoomID)):
|
||||
return roomID == detailStateRoomID
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ struct InvitedRoomProxyMockConfiguration {
|
||||
var id = UUID().uuidString
|
||||
var name: String?
|
||||
var avatarURL: URL?
|
||||
var isSpace = false
|
||||
var members: [RoomMemberProxyMock] = .allMembers
|
||||
var inviter: RoomMemberProxyMock = .mockAlice
|
||||
}
|
||||
@@ -44,7 +45,7 @@ extension RoomInfoProxyMock {
|
||||
avatarURL = configuration.avatarURL
|
||||
|
||||
isDirect = false
|
||||
isSpace = false
|
||||
isSpace = configuration.isSpace
|
||||
successor = nil
|
||||
isFavourite = false
|
||||
canonicalAlias = nil
|
||||
|
||||
@@ -341,4 +341,49 @@ extension Array where Element == RoomSummary {
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
]
|
||||
|
||||
static let mockSpaceInvites: [Element] = [
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "someAwesomeSpaceID1",
|
||||
joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie),
|
||||
name: "First space",
|
||||
isDirect: false,
|
||||
isSpace: true,
|
||||
avatarURL: .mockMXCAvatar,
|
||||
heroes: [],
|
||||
activeMembersCount: 0,
|
||||
lastMessage: nil,
|
||||
lastMessageDate: nil,
|
||||
unreadMessagesCount: 0,
|
||||
unreadMentionsCount: 0,
|
||||
unreadNotificationsCount: 0,
|
||||
notificationMode: nil,
|
||||
canonicalAlias: "#footest:somewhere.org",
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "someAwesomeSpaceID2",
|
||||
joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie),
|
||||
name: "Second space",
|
||||
isDirect: false,
|
||||
isSpace: true,
|
||||
avatarURL: nil,
|
||||
heroes: [],
|
||||
activeMembersCount: 0,
|
||||
lastMessage: nil,
|
||||
lastMessageDate: nil,
|
||||
unreadMessagesCount: 0,
|
||||
unreadMentionsCount: 0,
|
||||
unreadNotificationsCount: 0,
|
||||
notificationMode: nil,
|
||||
canonicalAlias: nil,
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ enum HomeScreenCoordinatorAction {
|
||||
case presentRoomDetails(roomIdentifier: String)
|
||||
case presentReportRoom(roomIdentifier: String)
|
||||
case presentDeclineAndBlock(userID: String, roomID: String)
|
||||
case presentSpace(SpaceRoomListProxyProtocol)
|
||||
case roomLeft(roomIdentifier: String)
|
||||
case transferOwnership(roomIdentifier: String)
|
||||
case presentSettingsScreen
|
||||
@@ -67,6 +68,10 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentRoomDetails(roomIdentifier: roomIdentifier))
|
||||
case .presentReportRoom(let roomIdentifier):
|
||||
actionsSubject.send(.presentReportRoom(roomIdentifier: roomIdentifier))
|
||||
case .presentDeclineAndBlock(let userID, let roomID):
|
||||
actionsSubject.send(.presentDeclineAndBlock(userID: userID, roomID: roomID))
|
||||
case .presentSpace(let spaceRoomListProxy):
|
||||
actionsSubject.send(.presentSpace(spaceRoomListProxy))
|
||||
case .roomLeft(roomIdentifier: let roomIdentifier):
|
||||
actionsSubject.send(.roomLeft(roomIdentifier: roomIdentifier))
|
||||
case .presentFeedbackScreen:
|
||||
@@ -85,8 +90,6 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentGlobalSearch)
|
||||
case .logout:
|
||||
actionsSubject.send(.logout)
|
||||
case .presentDeclineAndBlock(let userID, let roomID):
|
||||
actionsSubject.send(.presentDeclineAndBlock(userID: userID, roomID: roomID))
|
||||
case .transferOwnership(let roomIdentifier):
|
||||
actionsSubject.send(.transferOwnership(roomIdentifier: roomIdentifier))
|
||||
}
|
||||
|
||||
@@ -9,11 +9,12 @@ import Combine
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
enum HomeScreenViewModelAction: Equatable {
|
||||
enum HomeScreenViewModelAction {
|
||||
case presentRoom(roomIdentifier: String)
|
||||
case presentRoomDetails(roomIdentifier: String)
|
||||
case presentReportRoom(roomIdentifier: String)
|
||||
case presentDeclineAndBlock(userID: String, roomID: String)
|
||||
case presentSpace(SpaceRoomListProxyProtocol)
|
||||
case roomLeft(roomIdentifier: String)
|
||||
case transferOwnership(roomIdentifier: String)
|
||||
case presentSecureBackupSettings
|
||||
|
||||
@@ -414,11 +414,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
|
||||
switch await userSession.clientProxy.joinRoom(roomID, via: []) {
|
||||
case .success:
|
||||
actionsSubject.send(.presentRoom(roomIdentifier: roomID))
|
||||
analyticsService.trackJoinedRoom(isDM: roomProxy.info.isDirect,
|
||||
isSpace: roomProxy.info.isSpace,
|
||||
activeMemberCount: UInt(roomProxy.info.activeMembersCount))
|
||||
appSettings.seenInvites.remove(roomID)
|
||||
await finishAcceptInvite(roomProxy: roomProxy)
|
||||
case .failure(let error):
|
||||
switch error {
|
||||
case .invalidInvite:
|
||||
@@ -429,6 +425,28 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
private func finishAcceptInvite(roomProxy: InvitedRoomProxyProtocol) async {
|
||||
if roomProxy.info.isSpace {
|
||||
let spaceService = userSession.clientProxy.spaceService
|
||||
|
||||
switch await spaceService.spaceRoomList(spaceID: roomProxy.id, parent: nil) {
|
||||
case .success(let spaceRoomListProxy):
|
||||
actionsSubject.send(.presentSpace(spaceRoomListProxy))
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed to get the space room list after accepting invite: \(error)")
|
||||
displayError()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
actionsSubject.send(.presentRoom(roomIdentifier: roomProxy.id))
|
||||
}
|
||||
|
||||
analyticsService.trackJoinedRoom(isDM: roomProxy.info.isDirect,
|
||||
isSpace: roomProxy.info.isSpace,
|
||||
activeMemberCount: UInt(roomProxy.info.activeMembersCount))
|
||||
appSettings.seenInvites.remove(roomProxy.id)
|
||||
}
|
||||
|
||||
private func showDeclineInviteConfirmationAlert(roomID: String) async {
|
||||
guard let room = state.rooms.first(where: { $0.id == roomID }) else {
|
||||
displayError()
|
||||
|
||||
Reference in New Issue
Block a user