mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Add a RoomScreenHook.
This commit is contained in:
@@ -9,6 +9,10 @@ import Foundation
|
||||
|
||||
class AppHooks: AppHooksProtocol {
|
||||
#if IS_MAIN_APP
|
||||
func configure(with userSession: UserSessionProtocol?) async {
|
||||
await roomScreenHook.configure(with: userSession)
|
||||
}
|
||||
|
||||
private(set) var appSettingsHook: AppSettingsHookProtocol = DefaultAppSettingsHook()
|
||||
func registerAppSettingsHook(_ hook: AppSettingsHookProtocol) {
|
||||
appSettingsHook = hook
|
||||
@@ -28,6 +32,11 @@ class AppHooks: AppHooksProtocol {
|
||||
func registerCertificateValidatorHook(_ hook: CertificateValidatorHookProtocol) {
|
||||
certificateValidatorHook = hook
|
||||
}
|
||||
|
||||
private(set) var roomScreenHook: RoomScreenHookProtocol = DefaultRoomScreenHook()
|
||||
func registerRoomScreenHook(_ hook: RoomScreenHookProtocol) {
|
||||
roomScreenHook = hook
|
||||
}
|
||||
#endif
|
||||
|
||||
private(set) var clientBuilderHook: ClientBuilderHookProtocol = DefaultClientBuilderHook()
|
||||
@@ -38,6 +47,10 @@ class AppHooks: AppHooksProtocol {
|
||||
|
||||
protocol AppHooksProtocol {
|
||||
func setUp()
|
||||
|
||||
#if IS_MAIN_APP
|
||||
func configure(with userSession: UserSessionProtocol?) async
|
||||
#endif
|
||||
}
|
||||
|
||||
extension AppHooksProtocol {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol RoomScreenHookProtocol {
|
||||
func configure(with userSession: UserSessionProtocol?) async
|
||||
func update(_ viewState: RoomScreenViewState) -> RoomScreenViewState
|
||||
}
|
||||
|
||||
struct DefaultRoomScreenHook: RoomScreenHookProtocol {
|
||||
func configure(with userSession: UserSessionProtocol?) async { }
|
||||
func update(_ viewState: RoomScreenViewState) -> RoomScreenViewState { viewState }
|
||||
}
|
||||
@@ -36,6 +36,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
observeUserSessionChanges()
|
||||
startSync()
|
||||
performSettingsToAccountDataMigration(userSession: userSession)
|
||||
Task { await appHooks.configure(with: userSession) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>
|
||||
private let appMediator: AppMediatorProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let appHooks: AppHooks
|
||||
private let analytics: AnalyticsService
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
@@ -99,6 +100,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>,
|
||||
appMediator: AppMediatorProtocol,
|
||||
appSettings: AppSettings,
|
||||
appHooks: AppHooks,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) async {
|
||||
self.roomID = roomID
|
||||
@@ -110,6 +112,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
self.ongoingCallRoomIDPublisher = ongoingCallRoomIDPublisher
|
||||
self.appMediator = appMediator
|
||||
self.appSettings = appSettings
|
||||
self.appHooks = appHooks
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
@@ -510,6 +513,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher,
|
||||
appMediator: appMediator,
|
||||
appSettings: appSettings,
|
||||
appHooks: appHooks,
|
||||
composerDraftService: composerDraftService,
|
||||
timelineControllerFactory: timelineControllerFactory)
|
||||
|
||||
@@ -1451,6 +1455,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher,
|
||||
appMediator: appMediator,
|
||||
appSettings: appSettings,
|
||||
appHooks: appHooks,
|
||||
analytics: analytics,
|
||||
userIndicatorController: userIndicatorController)
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
|
||||
@@ -675,6 +675,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
ongoingCallRoomIDPublisher: elementCallService.ongoingCallRoomIDPublisher,
|
||||
appMediator: appMediator,
|
||||
appSettings: appSettings,
|
||||
appHooks: appHooks,
|
||||
analytics: analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ struct RoomScreenCoordinatorParameters {
|
||||
let ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>
|
||||
let appMediator: AppMediatorProtocol
|
||||
let appSettings: AppSettings
|
||||
let appHooks: AppHooks
|
||||
let composerDraftService: ComposerDraftServiceProtocol
|
||||
let timelineControllerFactory: TimelineControllerFactoryProtocol
|
||||
}
|
||||
@@ -73,6 +74,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
ongoingCallRoomIDPublisher: parameters.ongoingCallRoomIDPublisher,
|
||||
appMediator: parameters.appMediator,
|
||||
appSettings: parameters.appSettings,
|
||||
appHooks: parameters.appHooks,
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
|
||||
@@ -43,9 +43,18 @@ struct RoomScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
var canSendMessage = true
|
||||
|
||||
/// Whether or not starting a call is supported.
|
||||
var isCallingEnabled = true
|
||||
/// Whether or not the user is allowed to join calls in this room.
|
||||
var canJoinCall = false
|
||||
/// Whether or not this room currently has a call in progress.
|
||||
var hasOngoingCall: Bool
|
||||
var shouldShowCallButton = true
|
||||
/// Whether or not the user is already part of a call in another room.
|
||||
var isParticipatingInOngoingCall = false
|
||||
var shouldShowCallButton: Bool {
|
||||
isCallingEnabled && !isParticipatingInOngoingCall // Hide the join call button when already in the call
|
||||
}
|
||||
|
||||
var isKnockingEnabled = false
|
||||
var isKnockableRoom = false
|
||||
@@ -70,7 +79,7 @@ struct RoomScreenViewState: BindableState {
|
||||
|
||||
var footerDetails: RoomScreenFooterViewDetails?
|
||||
|
||||
var bindings: RoomScreenViewStateBindings
|
||||
var bindings = RoomScreenViewStateBindings()
|
||||
}
|
||||
|
||||
struct RoomScreenViewStateBindings {
|
||||
|
||||
@@ -57,6 +57,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>,
|
||||
appMediator: AppMediatorProtocol,
|
||||
appSettings: AppSettings,
|
||||
appHooks: AppHooks,
|
||||
analyticsService: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.clientProxy = clientProxy
|
||||
@@ -69,16 +70,15 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
self.initialSelectedPinnedEventID = initialSelectedPinnedEventID
|
||||
pinnedEventStringBuilder = .pinnedEventStringBuilder(userID: roomProxy.ownUserID)
|
||||
|
||||
super.init(initialViewState: .init(roomTitle: roomProxy.infoPublisher.value.displayName ?? roomProxy.id,
|
||||
roomAvatar: roomProxy.infoPublisher.value.avatar,
|
||||
hasOngoingCall: roomProxy.infoPublisher.value.hasRoomCall,
|
||||
hasSuccessor: roomProxy.infoPublisher.value.successor != nil,
|
||||
bindings: .init()),
|
||||
let viewState = RoomScreenViewState(roomTitle: roomProxy.infoPublisher.value.displayName ?? roomProxy.id,
|
||||
roomAvatar: roomProxy.infoPublisher.value.avatar,
|
||||
hasOngoingCall: roomProxy.infoPublisher.value.hasRoomCall,
|
||||
hasSuccessor: roomProxy.infoPublisher.value.successor != nil)
|
||||
super.init(initialViewState: appHooks.roomScreenHook.update(viewState),
|
||||
mediaProvider: mediaProvider)
|
||||
|
||||
Task {
|
||||
await handleRoomInfoUpdate(roomProxy.infoPublisher.value)
|
||||
|
||||
await updateVerificationBadge()
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] ongoingCallRoomID in
|
||||
guard let self else { return }
|
||||
state.shouldShowCallButton = ongoingCallRoomID != roomProxy.id
|
||||
state.isParticipatingInOngoingCall = ongoingCallRoomID == roomProxy.id
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -430,6 +430,7 @@ extension RoomScreenViewModel {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
|
||||
@@ -271,6 +271,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -291,6 +292,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -311,6 +313,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -331,6 +334,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -354,6 +358,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -377,6 +382,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -400,6 +406,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -424,6 +431,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -447,6 +455,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -469,6 +478,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -505,6 +515,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -528,6 +539,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
@@ -551,6 +563,7 @@ class MockScreen: Identifiable {
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
composerDraftService: ComposerDraftServiceMock(.init()),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
|
||||
Reference in New Issue
Block a user