mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Hook up the RoomThreadList to the RoomFlowCoordinator state machine and presenting threads.
This commit is contained in:
committed by
Stefan Ceriu
parent
212cd42161
commit
a358cacf31
@@ -394,6 +394,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.room, .presentPinnedEventsTimeline, .pinnedEventsTimeline):
|
case (.room, .presentPinnedEventsTimeline, .pinnedEventsTimeline):
|
||||||
startPinnedEventsTimelineFlow()
|
startPinnedEventsTimelineFlow()
|
||||||
|
|
||||||
|
// Thread List
|
||||||
|
|
||||||
|
case (.room, .presentThreadList, .threadList):
|
||||||
|
Task { await self.presentThreadList(animated: animated) }
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
|
||||||
case (_, .presentThread(let threadRootEventID, let focusEventID), .thread):
|
case (_, .presentThread(let threadRootEventID, let focusEventID), .thread):
|
||||||
@@ -721,9 +726,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case .presentKnockRequestsList:
|
case .presentKnockRequestsList:
|
||||||
stateMachine.tryEvent(.presentKnockRequestsListScreen)
|
stateMachine.tryEvent(.presentKnockRequestsListScreen)
|
||||||
case .presentThreadList:
|
case .presentThreadList:
|
||||||
Task {
|
stateMachine.tryEvent(.presentThreadList, userInfo: EventUserInfo(animated: animated))
|
||||||
await self.presentThreadList(animated: true)
|
|
||||||
}
|
|
||||||
case .presentThread(let threadRootEventID, let focussedEventID):
|
case .presentThread(let threadRootEventID, let focussedEventID):
|
||||||
stateMachine.tryEvent(.presentThread(threadRootEventID: threadRootEventID, focusEventID: focussedEventID))
|
stateMachine.tryEvent(.presentThread(threadRootEventID: threadRootEventID, focusEventID: focussedEventID))
|
||||||
case .presentRoom(let roomID, let via):
|
case .presentRoom(let roomID, let via):
|
||||||
@@ -738,12 +741,21 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func presentThreadList(animated: Bool) async {
|
private func presentThreadList(animated: Bool) async {
|
||||||
let coordinator = await RoomThreadListScreenCoordinator(parameters: .init(threadListServiceProxy: roomProxy.threadListService(),
|
let coordinator = RoomThreadListScreenCoordinator(parameters: .init(threadListServiceProxy: roomProxy.threadListService(),
|
||||||
mediaProvider: userSession.mediaProvider))
|
mediaProvider: userSession.mediaProvider))
|
||||||
|
|
||||||
coordinator.actionsPublisher.sink { [weak self] _ in }.store(in: &cancellables)
|
coordinator.actionsPublisher.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
switch action {
|
||||||
|
case .presentThread(let threadRootEventID):
|
||||||
|
stateMachine.tryEvent(.presentThread(threadRootEventID: threadRootEventID, focusEventID: nil))
|
||||||
|
}
|
||||||
|
}.store(in: &cancellables)
|
||||||
|
|
||||||
navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in }
|
navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
stateMachine.tryEvent(.dismissThreadList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentThread(threadRootEventID: String, focusEventID: String?, animated: Bool) async {
|
private func presentThread(threadRootEventID: String, focusEventID: String?, animated: Bool) async {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ extension RoomFlowCoordinator {
|
|||||||
case initial
|
case initial
|
||||||
case joinRoomScreen
|
case joinRoomScreen
|
||||||
case room
|
case room
|
||||||
|
case threadList
|
||||||
case thread(threadRootEventID: String, previousState: State)
|
case thread(threadRootEventID: String, previousState: State)
|
||||||
case roomDetails(isRoot: Bool)
|
case roomDetails(isRoot: Bool)
|
||||||
case roomDetailsEditScreen
|
case roomDetailsEditScreen
|
||||||
@@ -113,6 +114,9 @@ extension RoomFlowCoordinator {
|
|||||||
|
|
||||||
case presentThread(threadRootEventID: String, focusEventID: String?)
|
case presentThread(threadRootEventID: String, focusEventID: String?)
|
||||||
case dismissThread
|
case dismissThread
|
||||||
|
|
||||||
|
case presentThreadList
|
||||||
|
case dismissThreadList
|
||||||
|
|
||||||
case startSpaceFlow
|
case startSpaceFlow
|
||||||
case finishedSpaceFlow
|
case finishedSpaceFlow
|
||||||
@@ -236,6 +240,14 @@ extension RoomFlowCoordinator {
|
|||||||
case (.pinnedEventsTimeline(let previousState), .dismissPinnedEventsTimeline):
|
case (.pinnedEventsTimeline(let previousState), .dismissPinnedEventsTimeline):
|
||||||
return previousState
|
return previousState
|
||||||
|
|
||||||
|
// Thread List
|
||||||
|
case (.room, .presentThreadList):
|
||||||
|
return .threadList
|
||||||
|
case (.threadList, .dismissThreadList):
|
||||||
|
return .room
|
||||||
|
case (.threadList, .presentThread(let threadRootEventID, _)):
|
||||||
|
return .thread(threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
case (.room, .presentThread(let threadRootEventID, _)):
|
case (.room, .presentThread(let threadRootEventID, _)):
|
||||||
return .thread(threadRootEventID: threadRootEventID, previousState: fromState)
|
return .thread(threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|||||||
@@ -6984,12 +6984,12 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var threadListServiceClosure: (() async -> RoomThreadListServiceProxyProtocol)?
|
var threadListServiceClosure: (() -> RoomThreadListServiceProxyProtocol)?
|
||||||
|
|
||||||
func threadListService() async -> RoomThreadListServiceProxyProtocol {
|
func threadListService() -> RoomThreadListServiceProxyProtocol {
|
||||||
threadListServiceCallsCount += 1
|
threadListServiceCallsCount += 1
|
||||||
if let threadListServiceClosure = threadListServiceClosure {
|
if let threadListServiceClosure = threadListServiceClosure {
|
||||||
return await threadListServiceClosure()
|
return threadListServiceClosure()
|
||||||
} else {
|
} else {
|
||||||
return threadListServiceReturnValue
|
return threadListServiceReturnValue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ struct RoomThreadListScreenCoordinatorParameters {
|
|||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomThreadListScreenCoordinatorAction { }
|
enum RoomThreadListScreenCoordinatorAction {
|
||||||
|
case presentThread(threadRootEventID: String)
|
||||||
|
}
|
||||||
|
|
||||||
final class RoomThreadListScreenCoordinator: CoordinatorProtocol {
|
final class RoomThreadListScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: RoomThreadListScreenCoordinatorParameters
|
private let parameters: RoomThreadListScreenCoordinatorParameters
|
||||||
@@ -35,7 +37,13 @@ final class RoomThreadListScreenCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
viewModel.actionsPublisher.sink { [weak self] action in
|
viewModel.actionsPublisher.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
MXLog.info("Coordinator: received view model action: \(action)")
|
MXLog.info("Coordinator: received view model action: \(action)")
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .presentThread(let threadRootEventID):
|
||||||
|
actionsSubject.send(.presentThread(threadRootEventID: threadRootEventID))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum RoomThreadListScreenViewModelAction { }
|
enum RoomThreadListScreenViewModelAction {
|
||||||
|
case presentThread(threadRootEventID: String)
|
||||||
|
}
|
||||||
|
|
||||||
struct RoomThreadListScreenViewState: BindableState {
|
struct RoomThreadListScreenViewState: BindableState {
|
||||||
var items = [RoomThreadListItem]()
|
var items = [RoomThreadListItem]()
|
||||||
@@ -22,4 +24,5 @@ struct RoomThreadListScreenViewStateBindings { }
|
|||||||
enum RoomThreadListScreenViewAction {
|
enum RoomThreadListScreenViewAction {
|
||||||
case oldestItemDidAppear
|
case oldestItemDidAppear
|
||||||
case oldestItemDidDisappear
|
case oldestItemDidDisappear
|
||||||
|
case tappedThread(threadRootEventID: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ class RoomThreadListScreenViewModel: RoomThreadListScreenViewModelType, RoomThre
|
|||||||
}
|
}
|
||||||
case .oldestItemDidDisappear:
|
case .oldestItemDidDisappear:
|
||||||
isOldestItemVisible = false
|
isOldestItemVisible = false
|
||||||
|
case .tappedThread(let threadRootEventID):
|
||||||
|
actionsSubject.send(.presentThread(threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,14 @@ struct RoomThreadListScreen: View {
|
|||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(spacing: 0) {
|
LazyVStack(spacing: 0) {
|
||||||
ForEach(context.viewState.items) { item in
|
ForEach(context.viewState.items) { item in
|
||||||
RoomThreadListCell(item: item, mediaProvider: context.mediaProvider)
|
Button {
|
||||||
.padding(.horizontal, 16)
|
context.send(viewAction: .tappedThread(threadRootEventID: item.id))
|
||||||
.padding(.vertical, 8)
|
} label: {
|
||||||
|
RoomThreadListCell(item: item, mediaProvider: context.mediaProvider)
|
||||||
|
.padding(.horizontal, 16)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
.buttonStyle(ThreadCellButtonStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
footer
|
footer
|
||||||
@@ -137,6 +142,14 @@ private struct RoomThreadListCell: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct ThreadCellButtonStyle: ButtonStyle {
|
||||||
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
|
configuration.label
|
||||||
|
.background(configuration.isPressed ? Color.compound.bgSubtleSecondary : Color.compound.bgCanvasDefault)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
struct RoomThreadListScreen_Previews: PreviewProvider, TestablePreview {
|
struct RoomThreadListScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func threadListService() async -> RoomThreadListServiceProxyProtocol {
|
func threadListService() -> RoomThreadListServiceProxyProtocol {
|
||||||
RoomThreadListProxy(threadListService: room.threadListService(), eventStringBuilder: eventStringBuilder)
|
RoomThreadListProxy(threadListService: room.threadListService(), eventStringBuilder: eventStringBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
|||||||
|
|
||||||
func threadTimeline(eventID: String) async -> Result<TimelineProxyProtocol, RoomProxyError>
|
func threadTimeline(eventID: String) async -> Result<TimelineProxyProtocol, RoomProxyError>
|
||||||
|
|
||||||
func threadListService() async -> RoomThreadListServiceProxyProtocol
|
func threadListService() -> RoomThreadListServiceProxyProtocol
|
||||||
|
|
||||||
func loadOrFetchEventDetails(for eventID: String) async -> Result<TimelineEvent, RoomProxyError>
|
func loadOrFetchEventDetails(for eventID: String) async -> Result<TimelineEvent, RoomProxyError>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user