From 3923d65b41e81e8147c68ba27d8a9ca6bc53ae13 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 3 Jun 2025 17:52:55 +0300 Subject: [PATCH] Disable the threaded timeline composer when the room is read only. --- .../ThreadTimelineScreenCoordinator.swift | 2 +- .../ThreadTimelineScreenModels.swift | 2 ++ .../ThreadTimelineScreenViewModel.swift | 29 +++++++++++++++++-- .../View/ThreadTimelineScreen.swift | 19 ++++++------ 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenCoordinator.swift b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenCoordinator.swift index e82a2fc73..4fd35109a 100644 --- a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenCoordinator.swift +++ b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenCoordinator.swift @@ -55,7 +55,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol { init(parameters: ThreadTimelineScreenCoordinatorParameters) { self.parameters = parameters - viewModel = ThreadTimelineScreenViewModel() + viewModel = ThreadTimelineScreenViewModel(roomProxy: parameters.roomProxy) timelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, timelineController: parameters.timelineController, diff --git a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenModels.swift b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenModels.swift index d4bc7c619..24c01a6f3 100644 --- a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenModels.swift +++ b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenModels.swift @@ -10,6 +10,8 @@ import Foundation enum ThreadTimelineScreenViewModelAction { } struct ThreadTimelineScreenViewState: BindableState { + var canSendMessage = true + var bindings = ThreadTimelineScreenViewStateBindings() } diff --git a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift index ac8dc2415..66b58fa73 100644 --- a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift +++ b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift @@ -11,13 +11,32 @@ import SwiftUI typealias ThreadTimelineScreenViewModelType = StateStoreViewModel class ThreadTimelineScreenViewModel: ThreadTimelineScreenViewModelType, ThreadTimelineScreenViewModelProtocol { + private let roomProxy: JoinedRoomProxyProtocol + private let actionsSubject: PassthroughSubject = .init() var actionsPublisher: AnyPublisher { actionsSubject.eraseToAnyPublisher() } - - init() { + + init(roomProxy: JoinedRoomProxyProtocol) { + self.roomProxy = roomProxy + super.init(initialViewState: ThreadTimelineScreenViewState()) + + Task { [weak self] in + for await roomInfo in roomProxy.infoPublisher.receive(on: DispatchQueue.main).values { + guard !Task.isCancelled else { + return + } + + await self?.handleRoomInfoUpdate(roomInfo) + } + } + .store(in: &cancellables) + + Task { + await handleRoomInfoUpdate(roomProxy.infoPublisher.value) + } } // MARK: - Public @@ -42,4 +61,10 @@ class ThreadTimelineScreenViewModel: ThreadTimelineScreenViewModelType, ThreadTi state.bindings.mediaPreviewViewModel = mediaPreviewViewModel } + + // MARK: - Private + + private func handleRoomInfoUpdate(_ roomInfo: RoomInfoProxy) async { + state.canSendMessage = await (try? roomProxy.canUser(userID: roomProxy.ownUserID, sendMessage: .roomMessage).get()) == true + } } diff --git a/ElementX/Sources/Screens/ThreadTimelineScreen/View/ThreadTimelineScreen.swift b/ElementX/Sources/Screens/ThreadTimelineScreen/View/ThreadTimelineScreen.swift index 252cf367f..d9d8a8e22 100644 --- a/ElementX/Sources/Screens/ThreadTimelineScreen/View/ThreadTimelineScreen.swift +++ b/ElementX/Sources/Screens/ThreadTimelineScreen/View/ThreadTimelineScreen.swift @@ -64,16 +64,15 @@ struct ThreadTimelineScreen: View { @ViewBuilder private var composer: some View { - #warning("Check permissions here too") -// if roomContext.viewState.canSendMessage { - composerToolbar -// } else { -// Text(L10n.screenRoomTimelineNoPermissionToPost) -// .font(.compound.bodyLG) -// .foregroundStyle(.compound.textDisabled) -// .multilineTextAlignment(.center) -// .padding(.vertical, 10) // Matches the MessageComposerStyleModifier -// } + if context.viewState.canSendMessage { + composerToolbar + } else { + Text(L10n.screenRoomTimelineNoPermissionToPost) + .font(.compound.bodyLG) + .foregroundStyle(.compound.textDisabled) + .multilineTextAlignment(.center) + .padding(.vertical, 10) // Matches the MessageComposerStyleModifier + } } private var scrollToBottomButton: some View {