mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Add Event Routes to the flows (#2743)
This commit is contained in:
@@ -206,6 +206,18 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
} else {
|
||||
handleAppRoute(.childRoomAlias(alias))
|
||||
}
|
||||
case .event(let roomID, let eventID):
|
||||
if isExternalURL {
|
||||
handleAppRoute(route)
|
||||
} else {
|
||||
handleAppRoute(.childEvent(roomID: roomID, eventID: eventID))
|
||||
}
|
||||
case .eventOnRoomAlias(let alias, let eventID):
|
||||
if isExternalURL {
|
||||
handleAppRoute(route)
|
||||
} else {
|
||||
handleAppRoute(.childEventOnRoomAlias(alias: alias, eventID: eventID))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -24,16 +24,24 @@ enum AppRoute: Equatable {
|
||||
case roomList
|
||||
/// A room, shown as the root of the stack (popping any child rooms).
|
||||
case room(roomID: String)
|
||||
/// A room, shown as the root of the stack (popping any child rooms).
|
||||
/// The same as ``room`` but using a room alias.
|
||||
case roomAlias(String)
|
||||
/// A room, pushed as a child of any existing rooms on the stack.
|
||||
case childRoom(roomID: String)
|
||||
/// A room, pushed as a child of any existing rooms on the stack.
|
||||
/// The same as ``childRoom`` but using a room alias.
|
||||
case childRoomAlias(String)
|
||||
/// The information about a particular room.
|
||||
case roomDetails(roomID: String)
|
||||
/// The profile of a member within the current room.
|
||||
case roomMemberDetails(userID: String)
|
||||
/// An event within a room, shown as the root of the stack (popping any child rooms).
|
||||
case event(roomID: String, eventID: String)
|
||||
/// The same as ``event`` but using a room alias.
|
||||
case eventOnRoomAlias(alias: String, eventID: String)
|
||||
/// An event within a room, either within the last child on the stack or pushing a new child if needed.
|
||||
case childEvent(roomID: String, eventID: String)
|
||||
/// The same as ``childEvent`` but using a room alias.
|
||||
case childEventOnRoomAlias(alias: String, eventID: String)
|
||||
/// The profile of a matrix user (outside of a room).
|
||||
case userProfile(userID: String)
|
||||
/// An Element Call link generated outside of a chat room.
|
||||
@@ -133,6 +141,12 @@ struct MatrixPermalinkParser: URLParser {
|
||||
return .roomAlias(alias)
|
||||
case .user(let id):
|
||||
return .userProfile(userID: id)
|
||||
case .eventOnRoomId(let roomID, let eventID):
|
||||
// return .event(roomID: roomID, eventID: eventID)
|
||||
return nil
|
||||
case .eventOnRoomAlias(let alias, let eventID):
|
||||
// return .eventOnRoomAlias(alias: alias, eventID: eventID)
|
||||
return nil
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,6 +39,16 @@ enum RoomFlowCoordinatorAction: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// A value that represents where the room flow will be started.
|
||||
enum RoomFlowCoordinatorEntryPoint: Hashable {
|
||||
/// The flow will start by showing the room directly.
|
||||
case room
|
||||
/// The flow will start by showing the room, focussing on the supplied event ID.
|
||||
case eventID(String)
|
||||
/// The flow will start by showing the room's details.
|
||||
case roomDetails
|
||||
}
|
||||
|
||||
// swiftlint:disable:next type_body_length
|
||||
class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let roomID: String
|
||||
@@ -54,6 +64,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private var roomProxy: RoomProxyProtocol!
|
||||
|
||||
private var roomScreenCoordinator: RoomScreenCoordinator?
|
||||
private weak var joinRoomScreenCoordinator: JoinRoomScreenCoordinator?
|
||||
|
||||
// periphery:ignore - used to avoid deallocation
|
||||
@@ -118,7 +129,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
|
||||
childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
} else if roomID != roomProxy.id {
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID), userInfo: EventUserInfo(animated: animated))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room), userInfo: EventUserInfo(animated: animated))
|
||||
} else {
|
||||
MXLog.info("Ignoring presentation of the same room as a child of this one.")
|
||||
}
|
||||
@@ -143,12 +154,24 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
} else {
|
||||
stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID), userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
case .roomAlias, .childRoomAlias, .roomList, .userProfile, .genericCallLink, .oidcCallback, .settings, .chatBackupSettings:
|
||||
break
|
||||
case .event(let roomID, let eventID):
|
||||
Task { await handleRoomRoute(roomID: roomID, focussedEventID: eventID, animated: animated) }
|
||||
case .childEvent(let roomID, let eventID):
|
||||
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
|
||||
childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
} else if roomID != roomProxy.id {
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated))
|
||||
} else {
|
||||
roomScreenCoordinator?.focusOnEvent(eventID: eventID)
|
||||
}
|
||||
case .roomAlias, .childRoomAlias, .eventOnRoomAlias, .childEventOnRoomAlias:
|
||||
break // These are converted to a room ID route one level above.
|
||||
case .roomList, .userProfile, .genericCallLink, .oidcCallback, .settings, .chatBackupSettings:
|
||||
break // These routes can't be handled.
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRoomRoute(roomID: String, animated: Bool) async {
|
||||
private func handleRoomRoute(roomID: String, focussedEventID: String? = nil, animated: Bool) async {
|
||||
guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
@@ -159,7 +182,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch roomProxy.membership {
|
||||
case .joined:
|
||||
await storeAndSubscribeToRoomProxy(roomProxy)
|
||||
stateMachine.tryEvent(.presentRoom, userInfo: EventUserInfo(animated: animated))
|
||||
stateMachine.tryEvent(.presentRoom(focussedEventID: focussedEventID), userInfo: EventUserInfo(animated: animated))
|
||||
default:
|
||||
stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
@@ -307,7 +330,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// Child flow
|
||||
|
||||
case (_, .startChildFlow(let roomID)):
|
||||
case (_, .startChildFlow(let roomID, _)):
|
||||
return .presentingChild(childRoomID: roomID, previousState: fromState)
|
||||
case (.presentingChild(_, let previousState), .dismissChildFlow):
|
||||
return previousState
|
||||
@@ -328,8 +351,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case (_, .dismissJoinRoomScreen, .complete):
|
||||
dismissFlow(animated: animated)
|
||||
|
||||
case (_, .presentRoom, .room):
|
||||
Task { await self.presentRoom(fromState: context.fromState, animated: animated) }
|
||||
case (_, .presentRoom(let focussedEventID), .room):
|
||||
Task { await self.presentRoom(fromState: context.fromState, focussedEventID: focussedEventID, animated: animated) }
|
||||
case (_, .dismissFlow, .complete):
|
||||
dismissFlow(animated: animated)
|
||||
|
||||
@@ -438,8 +461,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
rolesAndPermissionsFlowCoordinator = nil
|
||||
|
||||
// Child flow
|
||||
case (_, .startChildFlow(let roomID), .presentingChild):
|
||||
Task { await self.startChildFlow(for: roomID) }
|
||||
case (_, .startChildFlow(let roomID, let entryPoint), .presentingChild):
|
||||
Task { await self.startChildFlow(for: roomID, entryPoint: entryPoint) }
|
||||
case (.presentingChild, .dismissChildFlow, _):
|
||||
childRoomFlowCoordinator = nil
|
||||
|
||||
@@ -467,8 +490,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
/// Updates the navigation stack so it displays the timeline for the given room
|
||||
/// - Parameters:
|
||||
/// - fromState: The state that asked for the room presentation.
|
||||
/// - focussedEventID: An (optional) event ID that the timeline should be focussed around.
|
||||
/// - animated: whether it should animate the transition
|
||||
private func presentRoom(fromState: State, animated: Bool) async {
|
||||
private func presentRoom(fromState: State, focussedEventID: String? = nil, animated: Bool) async {
|
||||
// If any sheets are presented dismiss them, rely on their dismissal callbacks to transition the state machine
|
||||
// through the correct states before presenting the room
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
@@ -507,6 +532,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy)
|
||||
|
||||
let parameters = RoomScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||
focussedEventID: focussedEventID,
|
||||
timelineController: timelineController,
|
||||
mediaProvider: userSession.mediaProvider,
|
||||
mediaPlayerProvider: MediaPlayerProvider(),
|
||||
@@ -548,6 +574,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
roomScreenCoordinator = coordinator
|
||||
if !isChildFlow {
|
||||
let animated = UIDevice.current.userInterfaceIdiom == .phone ? animated : false
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in
|
||||
@@ -584,7 +611,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
if let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) {
|
||||
await storeAndSubscribeToRoomProxy(roomProxy)
|
||||
stateMachine.tryEvent(.presentRoom, userInfo: EventUserInfo(animated: animated))
|
||||
stateMachine.tryEvent(.presentRoom(focussedEventID: nil), userInfo: EventUserInfo(animated: animated))
|
||||
|
||||
analytics.trackJoinedRoom(isDM: roomProxy.isDirect, isSpace: roomProxy.isSpace, activeMemberCount: UInt(roomProxy.activeMembersCount))
|
||||
} else {
|
||||
@@ -1022,7 +1049,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case .openUserProfile:
|
||||
stateMachine.tryEvent(.presentUserProfile(userID: userID))
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -1045,7 +1072,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch action {
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
|
||||
case .dismiss:
|
||||
break // Not supported when pushed.
|
||||
}
|
||||
@@ -1115,7 +1142,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// We don't need to worry about passing in the room proxy as timelines are
|
||||
// cached. The local echo will be visible when fetching the room by its ID.
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
|
||||
}
|
||||
|
||||
private func presentNotificationSettingsScreen() {
|
||||
@@ -1249,7 +1276,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// MARK: - Child Flow
|
||||
|
||||
private func startChildFlow(for roomID: String) async {
|
||||
private func startChildFlow(for roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint) async {
|
||||
let coordinator = await RoomFlowCoordinator(roomID: roomID,
|
||||
userSession: userSession,
|
||||
isChildFlow: true,
|
||||
@@ -1275,7 +1302,14 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
.store(in: &cancellables)
|
||||
|
||||
childRoomFlowCoordinator = coordinator
|
||||
coordinator.handleAppRoute(.room(roomID: roomID), animated: true)
|
||||
switch entryPoint {
|
||||
case .room:
|
||||
coordinator.handleAppRoute(.room(roomID: roomID), animated: true)
|
||||
case .eventID(let eventID):
|
||||
coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: true)
|
||||
case .roomDetails:
|
||||
coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1329,7 +1363,7 @@ private extension RoomFlowCoordinator {
|
||||
case presentJoinRoomScreen
|
||||
case dismissJoinRoomScreen
|
||||
|
||||
case presentRoom
|
||||
case presentRoom(focussedEventID: String?)
|
||||
case dismissFlow
|
||||
|
||||
case presentReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
||||
@@ -1384,7 +1418,7 @@ private extension RoomFlowCoordinator {
|
||||
case dismissRolesAndPermissionsScreen
|
||||
|
||||
// Child room flow events
|
||||
case startChildFlow(roomID: String)
|
||||
case startChildFlow(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint)
|
||||
case dismissChildFlow
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,39 +196,39 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch appRoute {
|
||||
case .room(let roomID):
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated))
|
||||
case .roomAlias(let alias):
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else {
|
||||
return
|
||||
}
|
||||
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
|
||||
await asyncHandleAppRoute(.room(roomID: roomID), animated: animated)
|
||||
case .childRoom(let roomID):
|
||||
if let roomFlowCoordinator {
|
||||
roomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated))
|
||||
}
|
||||
case .childRoomAlias(let alias):
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else {
|
||||
return
|
||||
}
|
||||
|
||||
if let roomFlowCoordinator {
|
||||
roomFlowCoordinator.handleAppRoute(.childRoom(roomID: roomID), animated: animated)
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
}
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
|
||||
await asyncHandleAppRoute(.childRoom(roomID: roomID), animated: animated)
|
||||
case .roomDetails(let roomID):
|
||||
if stateMachine.state.selectedRoomID == roomID {
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: true), userInfo: .init(animated: animated))
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .roomDetails), userInfo: .init(animated: animated))
|
||||
}
|
||||
case .roomList:
|
||||
roomFlowCoordinator?.clearRoute(animated: animated)
|
||||
case .roomMemberDetails:
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
case .event(let roomID, let eventID):
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: .init(animated: animated))
|
||||
case .eventOnRoomAlias(let alias, let eventID):
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
|
||||
await asyncHandleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated)
|
||||
case .childEvent:
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
case .childEventOnRoomAlias(let alias, let eventID):
|
||||
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
|
||||
await asyncHandleAppRoute(.childEvent(roomID: roomID, eventID: eventID), animated: animated)
|
||||
case .userProfile(let userID):
|
||||
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
|
||||
case .genericCallLink(let url):
|
||||
@@ -266,14 +266,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case (.initial, .start, .roomList):
|
||||
presentHomeScreen()
|
||||
attemptStartingOnboarding()
|
||||
|
||||
case(.roomList(let selectedRoomID), .selectRoom(let roomID, let showingRoomDetails), .roomList):
|
||||
case(.roomList(let selectedRoomID), .selectRoom(let roomID, let entryPoint), .roomList):
|
||||
if selectedRoomID == roomID {
|
||||
if let roomFlowCoordinator {
|
||||
roomFlowCoordinator.handleAppRoute(.room(roomID: roomID), animated: animated)
|
||||
let route: AppRoute = switch entryPoint {
|
||||
case .room: .room(roomID: roomID)
|
||||
case .eventID(let eventID): .event(roomID: roomID, eventID: eventID)
|
||||
case .roomDetails: .roomDetails(roomID: roomID)
|
||||
}
|
||||
roomFlowCoordinator.handleAppRoute(route, animated: animated)
|
||||
}
|
||||
} else {
|
||||
Task { await self.startRoomFlow(roomID: roomID, showingRoomDetails: showingRoomDetails, animated: animated) }
|
||||
Task { await self.startRoomFlow(roomID: roomID, entryPoint: entryPoint, animated: animated) }
|
||||
}
|
||||
case(.roomList, .deselectRoom, .roomList):
|
||||
dismissRoomFlow(animated: animated)
|
||||
@@ -442,7 +446,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// MARK: Room Flow
|
||||
|
||||
private func startRoomFlow(roomID: String, showingRoomDetails: Bool, animated: Bool) async {
|
||||
private func startRoomFlow(roomID: String,
|
||||
entryPoint: RoomFlowCoordinatorEntryPoint,
|
||||
animated: Bool) async {
|
||||
let coordinator = await RoomFlowCoordinator(roomID: roomID,
|
||||
userSession: userSession,
|
||||
isChildFlow: false,
|
||||
@@ -461,7 +467,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case .finished:
|
||||
stateMachine.processEvent(.deselectRoom)
|
||||
case .presentRoom(let roomID):
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false))
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
|
||||
case .presentCallScreen(let roomProxy):
|
||||
presentCallScreen(roomProxy: roomProxy)
|
||||
}
|
||||
@@ -474,10 +480,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
navigationSplitCoordinator.setDetailCoordinator(detailNavigationStackCoordinator, animated: animated)
|
||||
}
|
||||
|
||||
if showingRoomDetails {
|
||||
coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: animated)
|
||||
} else {
|
||||
switch entryPoint {
|
||||
case .room:
|
||||
coordinator.handleAppRoute(.room(roomID: roomID), animated: animated)
|
||||
case .eventID(let eventID):
|
||||
coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated)
|
||||
case .roomDetails:
|
||||
coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: animated)
|
||||
}
|
||||
|
||||
let availableInvitesCount = userSession.clientProxy.inviteSummaryProvider?.roomListPublisher.value.count ?? 0
|
||||
@@ -518,7 +527,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
case .openRoom(let roomID):
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
self.stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false))
|
||||
self.stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -540,7 +549,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
.sink { [weak self] action in
|
||||
switch action {
|
||||
case .openRoom(let roomID):
|
||||
self?.stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false))
|
||||
self?.stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -691,7 +700,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch action {
|
||||
case .openDirectChat(let roomID):
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false))
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
|
||||
case .dismiss:
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
@@ -75,8 +75,9 @@ class UserSessionFlowCoordinatorStateMachine {
|
||||
case start
|
||||
|
||||
/// Request presentation for a particular room
|
||||
/// - Parameter roomID:the room identifier
|
||||
case selectRoom(roomID: String, showingRoomDetails: Bool)
|
||||
/// - Parameter roomID: The room identifier
|
||||
/// - Parameter entryPoint: The starting point for the presented room.
|
||||
case selectRoom(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint)
|
||||
/// The room screen has been dismissed
|
||||
case deselectRoom
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import WysiwygComposer
|
||||
|
||||
struct RoomScreenCoordinatorParameters {
|
||||
let roomProxy: RoomProxyProtocol
|
||||
var focussedEventID: String?
|
||||
let timelineController: RoomTimelineControllerProtocol
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
let mediaPlayerProvider: MediaPlayerProviderProtocol
|
||||
@@ -59,6 +60,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
init(parameters: RoomScreenCoordinatorParameters) {
|
||||
viewModel = RoomScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
focussedEventID: parameters.focussedEventID,
|
||||
timelineController: parameters.timelineController,
|
||||
mediaProvider: parameters.mediaProvider,
|
||||
mediaPlayerProvider: parameters.mediaPlayerProvider,
|
||||
@@ -129,6 +131,10 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func focusOnEvent(eventID: String) {
|
||||
Task { await viewModel.focusOnEvent(eventID: eventID) }
|
||||
}
|
||||
|
||||
func stop() {
|
||||
viewModel.stop()
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private var paginateBackwardsTask: Task<Void, Never>?
|
||||
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
focussedEventID: String? = nil,
|
||||
timelineController: RoomTimelineControllerProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
mediaPlayerProvider: MediaPlayerProviderProtocol,
|
||||
@@ -90,6 +91,11 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
bindings: .init(reactionsCollapsed: [:])),
|
||||
imageProvider: mediaProvider)
|
||||
|
||||
// This may change to load the detached timeline directly.
|
||||
if let focussedEventID {
|
||||
Task { await focusOnEvent(eventID: focussedEventID) }
|
||||
}
|
||||
|
||||
setupSubscriptions()
|
||||
setupDirectRoomSubscriptionsIfNeeded()
|
||||
|
||||
@@ -208,6 +214,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
func focusOnEvent(eventID: String) async { }
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func attach(_ attachment: ComposerAttachmentType) {
|
||||
|
||||
@@ -23,5 +23,7 @@ protocol RoomScreenViewModelProtocol {
|
||||
var actions: AnyPublisher<RoomScreenViewModelAction, Never> { get }
|
||||
var context: RoomScreenViewModelType.Context { get }
|
||||
func process(composerAction: ComposerToolbarViewModelAction)
|
||||
/// Updates the timeline to show and highlight the item with the corresponding event ID.
|
||||
func focusOnEvent(eventID: String) async
|
||||
func stop()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user