Remove the CommonSettingsProtocol and use UserSession to carry multiple dependencies. (#6302)

* Remove the CommonSettingsProtocol.

* Replace multiple dependencies with the UserSession when it carries them.
This commit is contained in:
Doug
2026-10-09 10:20:00 +01:00
committed by GitHub
parent a3d170534c
commit 65bab49f39
75 changed files with 212 additions and 369 deletions
+4 -1
View File
@@ -273,7 +273,10 @@ Services = where product-level opinions live (Rust SDK stays spec-faithful).
- Inject via `init` parameters. - Inject via `init` parameters.
- Screen coordinators get `Parameters` struct with specific dependencies. - Screen coordinators get `Parameters` struct with specific dependencies.
- `CommonFlowParameters` flow-coordinator-only. - `CommonFlowParameters` flow-coordinator-only.
- `ServiceLocator` **deprecated** — never use services directly. Always inject from above. - `UserSession` = per-account dependency container (`clientProxy`, `userSettings`, `mediaProvider`…).
- Need 2+ from it? Pass `userSession` down. Need 1? Pass that one direct.
- Receiver may store only pieces it need (e.g. `clientProxy`, `userSettings`).
- Never pass `userSession` plus value it already owns (e.g. `userSession` + `userSettings`).
--- ---
@@ -15,11 +15,11 @@ enum RemoteSettingsError: Error {
protocol RemoteSettingsHookProtocol: Sendable { protocol RemoteSettingsHookProtocol: Sendable {
#if IS_MAIN_APP #if IS_MAIN_APP
@MainActor func initializeCache(using client: ClientProtocol, applyingTo appSettings: CommonSettingsProtocol) async -> Result<Void, RemoteSettingsError> @MainActor func initializeCache(using client: ClientProtocol, applyingTo appSettings: AppSettings) async -> Result<Void, RemoteSettingsError>
func updateCache(using client: ClientProtocol) async func updateCache(using client: ClientProtocol) async
@MainActor func reset(_ appSettings: CommonSettingsProtocol) @MainActor func reset(_ appSettings: AppSettings)
#endif #endif
@MainActor func loadCache(forHomeserver homeserver: String, applyingTo appSettings: CommonSettingsProtocol) @MainActor func loadCache(forHomeserver homeserver: String, applyingTo appSettings: AppSettings)
} }
struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol { struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
@@ -27,7 +27,7 @@ struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
/// A best effort implementation to let Element X advertise to users when they should be using /// A best effort implementation to let Element X advertise to users when they should be using
/// Element Pro. In an ideal world the backend would be able to validate the client's requests /// Element Pro. In an ideal world the backend would be able to validate the client's requests
/// instead of relying on it to check a well-known file for this. /// instead of relying on it to check a well-known file for this.
func initializeCache(using client: ClientProtocol, applyingTo appSettings: CommonSettingsProtocol) async -> Result<Void, RemoteSettingsError> { func initializeCache(using client: ClientProtocol, applyingTo appSettings: AppSettings) async -> Result<Void, RemoteSettingsError> {
guard case let .success(wellKnownData) = await client.elementWellKnown() else { guard case let .success(wellKnownData) = await client.elementWellKnown() else {
// Nothing to check, carry on as normal. // Nothing to check, carry on as normal.
return .success(()) return .success(())
@@ -49,10 +49,10 @@ struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
} }
func updateCache(using client: ClientProtocol) async { } func updateCache(using client: ClientProtocol) async { }
func reset(_ appSettings: any CommonSettingsProtocol) { } func reset(_ appSettings: AppSettings) { }
#endif #endif
func loadCache(forHomeserver homeserver: String, applyingTo appSettings: CommonSettingsProtocol) { } func loadCache(forHomeserver homeserver: String, applyingTo appSettings: AppSettings) { }
} }
private struct ElementWellKnown: Decodable { private struct ElementWellKnown: Decodable {
@@ -799,7 +799,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
emojiProvider: EmojiProvider(userSettings: userSession.userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: appMediator, appMediator: appMediator,
userSettings: userSession.userSettings, // TODO: @pixlwave Remove this in favour of the userSession.
appHooks: appHooks, appHooks: appHooks,
analytics: analyticsService, analytics: analyticsService,
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
@@ -31,7 +31,6 @@ struct CommonFlowParameters {
let emojiProvider: EmojiProviderProtocol let emojiProvider: EmojiProviderProtocol
let linkMetadataProvider: LinkMetadataProviderProtocol let linkMetadataProvider: LinkMetadataProviderProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let userSettings: UserSettings
let appHooks: AppHooks let appHooks: AppHooks
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
@@ -15,24 +15,6 @@ import Foundation
import Macros import Macros
import SwiftUI import SwiftUI
/// Common settings between app and NSE
nonisolated protocol CommonSettingsProtocol: AnyObject, Sendable {
var lastNotificationBootTime: TimeInterval? { get set }
var selectedNotificationTone: NotificationTone? { get set }
var lastKnownBadgeCount: Int { get set }
var logLevel: LogLevel { get }
var traceLogPacks: Set<TraceLogPack> { get }
var bugReportRageshakeURL: RemotePreference<RageshakeConfiguration> { get }
var contentScannerURL: RemotePreference<URL?> { get }
var forceDisableE2EE: RemotePreference<Bool> { get }
var mapTilerConfiguration: RemotePreference<MapTilerConfiguration> { get }
var enableOnlySignedDeviceIsolationMode: Bool { get }
var threadsEnabled: Bool { get }
var hideQuietNotificationAlerts: Bool { get }
}
nonisolated enum AppBuildType { nonisolated enum AppBuildType {
case debug case debug
case nightly case nightly
@@ -475,5 +457,3 @@ final nonisolated class AppSettings: @unchecked Sendable {
AppSettings(store: VolatileUserDefaults()) AppSettings(store: VolatileUserDefaults())
} }
} }
nonisolated extension AppSettings: CommonSettingsProtocol { }
@@ -377,7 +377,6 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol {
let parameters = HomeScreenCoordinatorParameters(userSession: userSession, let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
bugReportService: flowParameters.bugReportService, bugReportService: flowParameters.bugReportService,
selectedRoomPublisher: selectedRoomSubject.asCurrentValuePublisher(), selectedRoomPublisher: selectedRoomSubject.asCurrentValuePublisher(),
userSettings: flowParameters.userSettings,
analyticsService: flowParameters.analytics, analyticsService: flowParameters.analytics,
notificationManager: flowParameters.notificationManager, notificationManager: flowParameters.notificationManager,
userIndicatorController: flowParameters.userIndicatorController) userIndicatorController: flowParameters.userIndicatorController)
@@ -84,7 +84,6 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
userSession: userSession, userSession: userSession,
mediaPlayerProvider: MediaPlayerProvider(), mediaPlayerProvider: MediaPlayerProvider(),
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
userSettings: flowParameters.userSettings,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
emojiProvider: flowParameters.emojiProvider, emojiProvider: flowParameters.emojiProvider,
linkMetadataProvider: flowParameters.linkMetadataProvider, linkMetadataProvider: flowParameters.linkMetadataProvider,
@@ -69,7 +69,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
self.appLockService = appLockService self.appLockService = appLockService
analyticsService = flowParameters.analytics analyticsService = flowParameters.analytics
appMediator = flowParameters.appMediator appMediator = flowParameters.appMediator
userSettings = flowParameters.userSettings userSettings = flowParameters.userSession.userSettings
appHooks = flowParameters.appHooks appHooks = flowParameters.appHooks
notificationManager = flowParameters.notificationManager notificationManager = flowParameters.notificationManager
userIndicatorController = flowParameters.userIndicatorController userIndicatorController = flowParameters.userIndicatorController
@@ -281,8 +281,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController, let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController,
flow: .deviceInitiator, flow: .deviceInitiator,
userSettings: userSettings, userSession: userSession)
mediaProvider: userSession.mediaProvider)
let coordinator = SessionVerificationScreenCoordinator(parameters: parameters) let coordinator = SessionVerificationScreenCoordinator(parameters: parameters)
@@ -69,7 +69,6 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
userSession: userSession, userSession: userSession,
mediaPlayerProvider: MediaPlayerProvider(), mediaPlayerProvider: MediaPlayerProvider(),
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
userSettings: flowParameters.userSettings,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
emojiProvider: flowParameters.emojiProvider, emojiProvider: flowParameters.emojiProvider,
linkMetadataProvider: flowParameters.linkMetadataProvider, linkMetadataProvider: flowParameters.linkMetadataProvider,
@@ -107,15 +106,13 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
let stackCoordinator = NavigationStackCoordinator() let stackCoordinator = NavigationStackCoordinator()
let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode, let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode,
mapURLBuilder: flowParameters.userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSession.userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
liveLocationManager: flowParameters.userSession.liveLocationManager, userSession: userSession,
userSettings: flowParameters.userSettings,
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController)
mediaProvider: flowParameters.userSession.mediaProvider)
let coordinator = LocationSharingScreenCoordinator(parameters: params) let coordinator = LocationSharingScreenCoordinator(parameters: params)
coordinator.actions.sink { [weak self] action in coordinator.actions.sink { [weak self] action in
@@ -238,7 +238,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
defer { hideLoadingIndicator() } defer { hideLoadingIndicator() }
switch await roomProxy.loadOrFetchEventDetails(for: eventID) { switch await roomProxy.loadOrFetchEventDetails(for: eventID) {
case .success(let event): case .success(let event):
if flowParameters.userSettings.app.threadsEnabled, let threadRootEventID = event.threadRootEventId() { if userSession.userSettings.app.threadsEnabled, let threadRootEventID = event.threadRootEventId() {
if case .thread(threadRootEventID: threadRootEventID, _) = stateMachine.state, let threadCoordinator = childThreadScreenCoordinators.last { if case .thread(threadRootEventID: threadRootEventID, _) = stateMachine.state, let threadCoordinator = childThreadScreenCoordinators.last {
threadCoordinator.focusOnEvent(eventID: eventID) threadCoordinator.focusOnEvent(eventID: eventID)
} else { } else {
@@ -318,7 +318,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
// Otherwise check if the focussed event exists to handle a possible error or theaded event. // Otherwise check if the focussed event exists to handle a possible error or theaded event.
switch await roomProxy.loadOrFetchEventDetails(for: focusEvent.eventID) { switch await roomProxy.loadOrFetchEventDetails(for: focusEvent.eventID) {
case .success(let event): case .success(let event):
if flowParameters.userSettings.app.threadsEnabled, let threadRootEventID = event.threadRootEventId() { if userSession.userSettings.app.threadsEnabled, let threadRootEventID = event.threadRootEventId() {
stateMachine.tryEvent(.presentRoom(presentationAction: .thread(rootEventID: threadRootEventID, stateMachine.tryEvent(.presentRoom(presentationAction: .thread(rootEventID: threadRootEventID,
focusEvent: .init(eventID: focusEvent.eventID, focusEvent: .init(eventID: focusEvent.eventID,
shouldSetPin: focusEvent.shouldSetPin))), shouldSetPin: focusEvent.shouldSetPin))),
@@ -798,7 +798,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
linkMetadataProvider: flowParameters.linkMetadataProvider, linkMetadataProvider: flowParameters.linkMetadataProvider,
completionSuggestionService: completionSuggestionService, completionSuggestionService: completionSuggestionService,
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
userSettings: flowParameters.userSettings,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
composerDraftService: composerDraftService, composerDraftService: composerDraftService,
timelineControllerFactory: flowParameters.timelineControllerFactory, timelineControllerFactory: flowParameters.timelineControllerFactory,
@@ -855,8 +854,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private func presentJoinRoomScreen(via: [String], animated: Bool) { private func presentJoinRoomScreen(via: [String], animated: Bool) {
let coordinator = JoinRoomScreenCoordinator(parameters: .init(source: .generic(roomID: roomID, via: via), let coordinator = JoinRoomScreenCoordinator(parameters: .init(source: .generic(roomID: roomID, via: via),
userSession: userSession, userSession: userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController))
userSettings: flowParameters.userSettings))
joinRoomScreenCoordinator = coordinator joinRoomScreenCoordinator = coordinator
@@ -939,7 +937,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private func presentRoomDetails(isRoot: Bool, animated: Bool) async { private func presentRoomDetails(isRoot: Bool, animated: Bool) async {
let params = RoomDetailsScreenCoordinatorParameters(roomProxy: roomProxy, let params = RoomDetailsScreenCoordinatorParameters(roomProxy: roomProxy,
userSession: userSession, userSession: userSession,
userSettings: flowParameters.userSettings,
appHooks: flowParameters.appHooks, appHooks: flowParameters.appHooks,
analyticsService: flowParameters.analytics, analyticsService: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
@@ -1019,7 +1016,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(roomProxy: roomProxy, let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(roomProxy: roomProxy,
userSession: userSession, userSession: userSession,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: flowParameters.userSettings), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: userSession.userSettings),
navigationStackCoordinator: stackCoordinator, navigationStackCoordinator: stackCoordinator,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
orientationManager: flowParameters.appMediator.windowManager) orientationManager: flowParameters.appMediator.windowManager)
@@ -1119,9 +1116,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let parameters = MediaUploadPreviewScreenCoordinatorParameters(mediaURLs: mediaURLs, let parameters = MediaUploadPreviewScreenCoordinatorParameters(mediaURLs: mediaURLs,
caption: caption, caption: caption,
title: title, title: title,
shouldShowCaptionWarning: flowParameters.userSettings.app.shouldShowMediaCaptionWarning, shouldShowCaptionWarning: userSession.userSettings.app.shouldShowMediaCaptionWarning,
galleryEnabled: flowParameters.userSettings.app.galleryEnabled, galleryEnabled: userSession.userSettings.app.galleryEnabled,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: flowParameters.userSettings), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: userSession.userSettings),
timelineController: timelineController, timelineController: timelineController,
clientProxy: userSession.clientProxy, clientProxy: userSession.clientProxy,
userIndicatorController: flowParameters.userIndicatorController) userIndicatorController: flowParameters.userIndicatorController)
@@ -1176,15 +1173,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let stackCoordinator = NavigationStackCoordinator() let stackCoordinator = NavigationStackCoordinator()
let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode, let params = LocationSharingScreenCoordinatorParameters(interactionMode: interactionMode,
mapURLBuilder: flowParameters.userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSession.userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
liveLocationManager: flowParameters.userSession.liveLocationManager, userSession: userSession,
userSettings: flowParameters.userSettings,
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController)
mediaProvider: flowParameters.userSession.mediaProvider)
let coordinator = LocationSharingScreenCoordinator(parameters: params) let coordinator = LocationSharingScreenCoordinator(parameters: params)
coordinator.actions.sink { [weak self] action in coordinator.actions.sink { [weak self] action in
@@ -1324,8 +1319,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
userSession: userSession, userSession: userSession,
userNotificationCenter: UNUserNotificationCenter.current(), userNotificationCenter: UNUserNotificationCenter.current(),
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
isModallyPresented: true, isModallyPresented: true)
userSettings: flowParameters.userSettings)
let coordinator = NotificationSettingsScreenCoordinator(parameters: parameters) let coordinator = NotificationSettingsScreenCoordinator(parameters: parameters)
coordinator.actions.sink { [weak self] action in coordinator.actions.sink { [weak self] action in
switch action { switch action {
@@ -1418,9 +1412,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private func presentSecurityAndPrivacyScreen() { private func presentSecurityAndPrivacyScreen() {
let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy, let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy,
clientProxy: userSession.clientProxy, userSession: userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
appSetting: flowParameters.userSettings,
appHooks: flowParameters.appHooks)) appHooks: flowParameters.appHooks))
coordinator.actionsPublisher.sink { [weak self] action in coordinator.actionsPublisher.sink { [weak self] action in
@@ -23,6 +23,10 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
private let navigationStackCoordinator: NavigationStackCoordinator private let navigationStackCoordinator: NavigationStackCoordinator
private let flowParameters: CommonFlowParameters private let flowParameters: CommonFlowParameters
private var userSettings: UserSettings {
flowParameters.userSession.userSettings
}
// periphery:ignore - retaining purpose // periphery:ignore - retaining purpose
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator? private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
private var bugReportFlowCoordinator: BugReportFlowCoordinator? private var bugReportFlowCoordinator: BugReportFlowCoordinator?
@@ -73,7 +77,6 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
private func presentSettingsScreen(animated: Bool) { private func presentSettingsScreen(animated: Bool) {
let settingsScreenCoordinator = SettingsScreenCoordinator(parameters: .init(userSession: flowParameters.userSession, let settingsScreenCoordinator = SettingsScreenCoordinator(parameters: .init(userSession: flowParameters.userSession,
userSettings: flowParameters.userSettings,
isBugReportServiceEnabled: flowParameters.bugReportService.isEnabled, isBugReportServiceEnabled: flowParameters.bugReportService.isEnabled,
isInSecondaryWindow: isInSecondaryWindow, isInSecondaryWindow: isInSecondaryWindow,
userIndicatorController: flowParameters.userIndicatorController)) userIndicatorController: flowParameters.userIndicatorController))
@@ -139,7 +142,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
} }
private func presentLabs() { private func presentLabs() {
let coordinator = LabsScreenCoordinator(parameters: .init(userSettings: flowParameters.userSettings)) let coordinator = LabsScreenCoordinator(parameters: .init(userSettings: userSettings))
coordinator.actions coordinator.actions
.sink { [weak self] action in .sink { [weak self] action in
switch action { switch action {
@@ -190,7 +193,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
private func presentUserDetailsEditScreen() { private func presentUserDetailsEditScreen() {
let coordinator = UserDetailsEditScreenCoordinator(parameters: .init(orientationManager: flowParameters.windowManager, let coordinator = UserDetailsEditScreenCoordinator(parameters: .init(orientationManager: flowParameters.windowManager,
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: flowParameters.userSettings), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: userSettings),
navigationStackCoordinator: navigationStackCoordinator, navigationStackCoordinator: navigationStackCoordinator,
userIndicatorController: flowParameters.userIndicatorController)) userIndicatorController: flowParameters.userIndicatorController))
coordinator.actions coordinator.actions
@@ -234,7 +237,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
} }
private func presentAnalyticsScreen() { private func presentAnalyticsScreen() {
let coordinator = AnalyticsSettingsScreenCoordinator(parameters: .init(userSettings: flowParameters.userSettings, let coordinator = AnalyticsSettingsScreenCoordinator(parameters: .init(userSettings: userSettings,
analytics: flowParameters.analytics)) analytics: flowParameters.analytics))
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
} }
@@ -260,11 +263,11 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
} }
private func presentLegalInformationScreen() { private func presentLegalInformationScreen() {
navigationStackCoordinator.push(LegalInformationScreenCoordinator(userSettings: flowParameters.userSettings)) navigationStackCoordinator.push(LegalInformationScreenCoordinator(userSettings: userSettings))
} }
private func presentBlockedUsersScreen() { private func presentBlockedUsersScreen() {
let coordinator = BlockedUsersScreenCoordinator(parameters: .init(hideProfiles: flowParameters.userSettings.app.hideIgnoredUserProfiles, let coordinator = BlockedUsersScreenCoordinator(parameters: .init(hideProfiles: userSettings.app.hideIgnoredUserProfiles,
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController)) userIndicatorController: flowParameters.userIndicatorController))
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
@@ -275,8 +278,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
userNotificationCenter: UNUserNotificationCenter.current(), userNotificationCenter: UNUserNotificationCenter.current(),
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
isModallyPresented: false, isModallyPresented: false)
userSettings: flowParameters.userSettings)
let coordinator = NotificationSettingsScreenCoordinator(parameters: notificationParameters) let coordinator = NotificationSettingsScreenCoordinator(parameters: notificationParameters)
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
} }
@@ -300,20 +302,20 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
} }
private func presentMediaUploadQualitySettings() { private func presentMediaUploadQualitySettings() {
let parameters = MediaUploadQualitySettingsScreenCoordinatorParameters(userSettings: flowParameters.userSettings, let parameters = MediaUploadQualitySettingsScreenCoordinatorParameters(userSettings: userSettings,
analytics: flowParameters.analytics) analytics: flowParameters.analytics)
let coordinator = MediaUploadQualitySettingsScreenCoordinator(parameters: parameters) let coordinator = MediaUploadQualitySettingsScreenCoordinator(parameters: parameters)
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
} }
private func presentLocationSharingSettings() { private func presentLocationSharingSettings() {
let parameters = LocationSharingSettingsScreenCoordinatorParameters(userSettings: flowParameters.userSettings) let parameters = LocationSharingSettingsScreenCoordinatorParameters(userSettings: userSettings)
let coordinator = LocationSharingSettingsScreenCoordinator(parameters: parameters) let coordinator = LocationSharingSettingsScreenCoordinator(parameters: parameters)
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
} }
private func presentDeveloperOptions() { private func presentDeveloperOptions() {
let coordinator = DeveloperOptionsScreenCoordinator(appSettings: flowParameters.userSettings.app, let coordinator = DeveloperOptionsScreenCoordinator(appSettings: userSettings.app,
appHooks: flowParameters.appHooks, appHooks: flowParameters.appHooks,
clientProxy: flowParameters.userSession.clientProxy) clientProxy: flowParameters.userSession.clientProxy)
@@ -359,7 +361,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
accountSettingsPresenter = OAuthAccountSettingsPresenter(accountURL: url, accountSettingsPresenter = OAuthAccountSettingsPresenter(accountURL: url,
presentationAnchor: flowParameters.windowManager.mainWindow, presentationAnchor: flowParameters.windowManager.mainWindow,
appMediator: flowParameters.appMediator, appMediator: flowParameters.appMediator,
userSettings: flowParameters.userSettings, userSettings: userSettings,
appHooks: flowParameters.appHooks, appHooks: flowParameters.appHooks,
continuation: continuation) continuation: continuation)
accountSettingsPresenter?.start() accountSettingsPresenter?.start()
@@ -399,8 +399,7 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
let parameters = JoinRoomScreenCoordinatorParameters(source: .space(spaceServiceRoom), let parameters = JoinRoomScreenCoordinatorParameters(source: .space(spaceServiceRoom),
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController)
userSettings: flowParameters.userSettings)
let coordinator = JoinRoomScreenCoordinator(parameters: parameters) let coordinator = JoinRoomScreenCoordinator(parameters: parameters)
coordinator.actionsPublisher coordinator.actionsPublisher
.sink { [weak self] action in .sink { [weak self] action in
@@ -211,7 +211,6 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
private func presentSpaceSettings(animated: Bool) { private func presentSpaceSettings(animated: Bool) {
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy, let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
userSettings: flowParameters.userSettings,
appHooks: flowParameters.appHooks, appHooks: flowParameters.appHooks,
analyticsService: flowParameters.analytics, analyticsService: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
@@ -252,7 +251,7 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
let stackCoordinator = NavigationStackCoordinator() let stackCoordinator = NavigationStackCoordinator()
let parameters = RoomDetailsEditScreenCoordinatorParameters(roomProxy: roomProxy, let parameters = RoomDetailsEditScreenCoordinatorParameters(roomProxy: roomProxy,
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: flowParameters.userSettings), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: flowParameters.userSession.userSettings),
navigationStackCoordinator: stackCoordinator, navigationStackCoordinator: stackCoordinator,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
orientationManager: flowParameters.appMediator.windowManager) orientationManager: flowParameters.appMediator.windowManager)
@@ -276,9 +275,8 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
private func presentSecurityAndPrivacyScreen() { private func presentSecurityAndPrivacyScreen() {
let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy, let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy,
clientProxy: flowParameters.userSession.clientProxy, userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
appSetting: flowParameters.userSettings,
appHooks: flowParameters.appHooks)) appHooks: flowParameters.appHooks))
coordinator.actionsPublisher.sink { [weak self] action in coordinator.actionsPublisher.sink { [weak self] action in
@@ -214,7 +214,6 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
shouldShowCancelButton: isRoot, shouldShowCancelButton: isRoot,
userSession: flowParameters.userSession, userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
userSettings: flowParameters.userSettings,
analytics: flowParameters.analytics, analytics: flowParameters.analytics,
appHooks: flowParameters.appHooks) appHooks: flowParameters.appHooks)
let coordinator = CreateRoomScreenCoordinator(parameters: createParameters) let coordinator = CreateRoomScreenCoordinator(parameters: createParameters)
@@ -82,29 +82,27 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
self.appLockService = appLockService self.appLockService = appLockService
self.flowParameters = flowParameters self.flowParameters = flowParameters
presenceService = PresenceService(clientProxy: flowParameters.userSession.clientProxy, presenceService = PresenceService(clientProxy: flowParameters.userSession.clientProxy,
userSettings: flowParameters.userSettings) userSettings: flowParameters.userSession.userSettings)
navigationTabCoordinator = NavigationTabCoordinator() navigationTabCoordinator = NavigationTabCoordinator()
navigationRootCoordinator.setRootCoordinator(navigationTabCoordinator) navigationRootCoordinator.setRootCoordinator(navigationTabCoordinator)
let chatsSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: flowParameters.userSettings.app.hideBrandChrome)) let chatsSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: flowParameters.userSession.userSettings.app.hideBrandChrome))
chatsTabFlowCoordinator = ChatsTabFlowCoordinator(navigationSplitCoordinator: chatsSplitCoordinator, chatsTabFlowCoordinator = ChatsTabFlowCoordinator(navigationSplitCoordinator: chatsSplitCoordinator,
flowParameters: flowParameters) flowParameters: flowParameters)
chatsTabDetails = .init(tag: HomeTab.chats, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid) chatsTabDetails = .init(tag: HomeTab.chats, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid)
chatsTabDetails.navigationSplitCoordinator = chatsSplitCoordinator chatsTabDetails.navigationSplitCoordinator = chatsSplitCoordinator
let spacesSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: flowParameters.userSettings.app.hideBrandChrome)) let spacesSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: flowParameters.userSession.userSettings.app.hideBrandChrome))
spacesTabFlowCoordinator = SpacesTabFlowCoordinator(navigationSplitCoordinator: spacesSplitCoordinator, spacesTabFlowCoordinator = SpacesTabFlowCoordinator(navigationSplitCoordinator: spacesSplitCoordinator,
flowParameters: flowParameters) flowParameters: flowParameters)
spacesTabDetails = .init(tag: HomeTab.spaces, title: L10n.screenHomeTabSpaces, icon: \.space, selectedIcon: \.spaceSolid) spacesTabDetails = .init(tag: HomeTab.spaces, title: L10n.screenHomeTabSpaces, icon: \.space, selectedIcon: \.spaceSolid)
spacesTabDetails.navigationSplitCoordinator = spacesSplitCoordinator spacesTabDetails.navigationSplitCoordinator = spacesSplitCoordinator
if flowParameters.userSettings.app.globalSearchEnabled, #available(iOS 26.0, *) { if flowParameters.userSession.userSettings.app.globalSearchEnabled, #available(iOS 26.0, *) {
let searchCoordinator = SearchScreenCoordinator(parameters: .init(roomSummaryProvider: flowParameters.userSession.clientProxy.alternateRoomSummaryProvider, let searchCoordinator = SearchScreenCoordinator(parameters: .init(roomSummaryProvider: flowParameters.userSession.clientProxy.alternateRoomSummaryProvider,
clientProxy: flowParameters.userSession.clientProxy, userSession: flowParameters.userSession,
mediaProvider: flowParameters.userSession.mediaProvider, userIndicatorController: flowParameters.userIndicatorController))
userIndicatorController: flowParameters.userIndicatorController,
userSettings: flowParameters.userSettings))
let searchStackCoordinator = NavigationStackCoordinator() let searchStackCoordinator = NavigationStackCoordinator()
searchStackCoordinator.setRootCoordinator(searchCoordinator) searchStackCoordinator.setRootCoordinator(searchCoordinator)
@@ -426,8 +424,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController, let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController,
flow: flow, flow: flow,
userSettings: flowParameters.userSettings, userSession: userSession)
mediaProvider: userSession.mediaProvider)
let coordinator = SessionVerificationScreenCoordinator(parameters: parameters) let coordinator = SessionVerificationScreenCoordinator(parameters: parameters)
@@ -464,8 +461,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
presentCallScreen(configuration: .init(roomProxy: roomProxy, presentCallScreen(configuration: .init(roomProxy: roomProxy,
clientProxy: userSession.clientProxy, clientProxy: userSession.clientProxy,
clientID: InfoPlistReader.main.bundleIdentifier, clientID: InfoPlistReader.main.bundleIdentifier,
elementCallBaseURL: flowParameters.userSettings.app.elementCallBaseURL, elementCallBaseURL: userSession.userSettings.app.elementCallBaseURL,
elementCallBaseURLOverride: flowParameters.userSettings.app.elementCallBaseURLOverride, elementCallBaseURLOverride: userSession.userSettings.app.elementCallBaseURLOverride,
voiceOnly: voiceOnly, voiceOnly: voiceOnly,
colorScheme: colorScheme)) colorScheme: colorScheme))
} }
@@ -487,7 +484,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: flowParameters.elementCallService, let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: flowParameters.elementCallService,
configuration: configuration, configuration: configuration,
allowPictureInPicture: true, allowPictureInPicture: true,
userSettings: flowParameters.userSettings, userSettings: userSession.userSettings,
analytics: flowParameters.analytics)) analytics: flowParameters.analytics))
callScreenCoordinator.actions callScreenCoordinator.actions
@@ -2357,14 +2357,14 @@ nonisolated class ClientFactoryMock: ClientFactoryProtocol, @unchecked Sendable
return makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksCallsCount > 0 return makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksCallsCount > 0
} }
private let makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock = NSLock() private let makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments: (credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: CommonSettingsProtocol, appHooks: AppHooks)? private nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments: (credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: UserSettings, appHooks: AppHooks)?
var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArguments: (credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: CommonSettingsProtocol, appHooks: AppHooks)? { var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArguments: (credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: UserSettings, appHooks: AppHooks)? {
get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments } } get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments } }
set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments = newValue } } set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedArgumentsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedArguments = newValue } }
} }
private let makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock = NSLock() private let makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations: [(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: CommonSettingsProtocol, appHooks: AppHooks)] = [] private nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations: [(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: UserSettings, appHooks: AppHooks)] = []
var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocations: [(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: CommonSettingsProtocol, appHooks: AppHooks)] { var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocations: [(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: UserSettings, appHooks: AppHooks)] {
get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations } } get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations } }
set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations = newValue } } set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReceivedInvocationsLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReceivedInvocations = newValue } }
} }
@@ -2375,9 +2375,9 @@ nonisolated class ClientFactoryMock: ClientFactoryProtocol, @unchecked Sendable
get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReturnValueLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReturnValue } } get { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReturnValueLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReturnValue } }
set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReturnValueLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReturnValue = newValue } } set { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksReturnValueLock.withLock { makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksUnderlyingReturnValue = newValue } }
} }
nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksClosure: ((KeychainCredentials, String, ClientSessionDelegate, CommonSettingsProtocol, AppHooks) async throws -> ClientProtocol)? nonisolated(unsafe) var makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksClosure: ((KeychainCredentials, String, ClientSessionDelegate, UserSettings, AppHooks) async throws -> ClientProtocol)?
@concurrent func makeNSEClient(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: CommonSettingsProtocol, appHooks: AppHooks) async throws -> ClientProtocol { @concurrent func makeNSEClient(credentials: KeychainCredentials, roomID: String, clientSessionDelegate: ClientSessionDelegate, userSettings: UserSettings, appHooks: AppHooks) async throws -> ClientProtocol {
if let error = makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksThrowableError { if let error = makeNSEClientCredentialsRoomIDClientSessionDelegateUserSettingsAppHooksThrowableError {
throw error throw error
} }
+2 -1
View File
@@ -13,6 +13,7 @@ struct UserSessionMockConfiguration {
var clientProxy: ClientProxyProtocol = ClientProxyMock(.init()) var clientProxy: ClientProxyProtocol = ClientProxyMock(.init())
var userSettings: UserSettings = .mock() var userSettings: UserSettings = .mock()
var contentScannerService: ContentScannerServiceProtocol? var contentScannerService: ContentScannerServiceProtocol?
var liveLocationManager: LiveLocationManagerProtocol = LiveLocationManagerMock(.init())
} }
@MainActor extension UserSessionMock { @MainActor extension UserSessionMock {
@@ -28,6 +29,6 @@ struct UserSessionMockConfiguration {
sessionSecurityStatePublisher = CurrentValueSubject<SessionSecurityState, Never>(.init(verificationState: .verified, recoveryState: .enabled)).asCurrentValuePublisher() sessionSecurityStatePublisher = CurrentValueSubject<SessionSecurityState, Never>(.init(verificationState: .verified, recoveryState: .enabled)).asCurrentValuePublisher()
liveLocationManager = LiveLocationManagerMock(.init()) liveLocationManager = configuration.liveLocationManager
} }
} }
@@ -15,7 +15,6 @@ struct CreateRoomScreenCoordinatorParameters {
let shouldShowCancelButton: Bool let shouldShowCancelButton: Bool
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let userSettings: UserSettings
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let appHooks: AppHooks let appHooks: AppHooks
} }
@@ -42,7 +41,6 @@ final class CreateRoomScreenCoordinator: CoordinatorProtocol {
userSession: parameters.userSession, userSession: parameters.userSession,
analytics: parameters.analytics, analytics: parameters.analytics,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
userSettings: parameters.userSettings,
appHooks: parameters.appHooks) appHooks: parameters.appHooks)
} }
@@ -33,10 +33,9 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
analytics: AnalyticsServiceProtocol, analytics: AnalyticsServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
userSettings: UserSettings,
appHooks: AppHooks) { appHooks: AppHooks) {
self.userSession = userSession self.userSession = userSession
mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings) mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSession.userSettings)
self.analytics = analytics self.analytics = analytics
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
@@ -64,7 +63,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
shouldShowCancelButton: shouldShowCancelButton, shouldShowCancelButton: shouldShowCancelButton,
roomName: "", roomName: "",
serverName: userSession.clientProxy.userIDServerName ?? "", serverName: userSession.clientProxy.userIDServerName ?? "",
isKnockingFeatureEnabled: userSettings.app.knockingEnabled, isKnockingFeatureEnabled: userSession.userSettings.app.knockingEnabled,
canSelectSpace: canSelectSpace, canSelectSpace: canSelectSpace,
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""), aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
bindings: bindings) bindings: bindings)
@@ -459,7 +459,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
clientProxy.isAliasAvailableReturnValue = .success(isAliasAvailable) clientProxy.isAliasAvailableReturnValue = .success(isAliasAvailable)
let spaces = [SpaceServiceRoom].mockJoinedSpaces2 let spaces = [SpaceServiceRoom].mockJoinedSpaces2
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: spaces)) clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: spaces))
let userSession = UserSessionMock(.init(clientProxy: clientProxy)) let userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
return CreateRoomScreenViewModel(isSpace: isSpace, return CreateRoomScreenViewModel(isSpace: isSpace,
spaceSelectionMode: selectionMode, spaceSelectionMode: selectionMode,
@@ -467,7 +467,6 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
} }
} }
@@ -65,15 +65,12 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2)) clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
let userSession = UserSessionMock(.init(clientProxy: clientProxy)) let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let userSettings = UserSettings.mock()
return CreateRoomScreenViewModel(isSpace: false, return CreateRoomScreenViewModel(isSpace: false,
spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil), spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil),
shouldShowCancelButton: false, shouldShowCancelButton: false,
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
@@ -13,7 +13,6 @@ struct HomeScreenCoordinatorParameters {
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let bugReportService: BugReportServiceProtocol let bugReportService: BugReportServiceProtocol
let selectedRoomPublisher: CurrentValuePublisher<String?, Never> let selectedRoomPublisher: CurrentValuePublisher<String?, Never>
let userSettings: UserSettings
let analyticsService: AnalyticsServiceProtocol let analyticsService: AnalyticsServiceProtocol
let notificationManager: NotificationManagerProtocol let notificationManager: NotificationManagerProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
@@ -50,7 +49,6 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
init(parameters: HomeScreenCoordinatorParameters) { init(parameters: HomeScreenCoordinatorParameters) {
viewModel = HomeScreenViewModel(userSession: parameters.userSession, viewModel = HomeScreenViewModel(userSession: parameters.userSession,
selectedRoomPublisher: parameters.selectedRoomPublisher, selectedRoomPublisher: parameters.selectedRoomPublisher,
userSettings: parameters.userSettings,
analyticsService: parameters.analyticsService, analyticsService: parameters.analyticsService,
bugReportService: parameters.bugReportService, bugReportService: parameters.bugReportService,
notificationManager: parameters.notificationManager, notificationManager: parameters.notificationManager,
@@ -32,7 +32,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
// swiftlint:disable:next function_body_length // swiftlint:disable:next function_body_length
init(userSession: UserSessionProtocol, init(userSession: UserSessionProtocol,
selectedRoomPublisher: CurrentValuePublisher<String?, Never>, selectedRoomPublisher: CurrentValuePublisher<String?, Never>,
userSettings: UserSettings,
analyticsService: AnalyticsServiceProtocol, analyticsService: AnalyticsServiceProtocol,
bugReportService: BugReportServiceProtocol, bugReportService: BugReportServiceProtocol,
notificationManager: NotificationManagerProtocol, notificationManager: NotificationManagerProtocol,
@@ -40,7 +39,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
self.userSession = userSession self.userSession = userSession
self.analyticsService = analyticsService self.analyticsService = analyticsService
self.bugReportService = bugReportService self.bugReportService = bugReportService
self.userSettings = userSettings userSettings = userSession.userSettings
self.notificationManager = notificationManager self.notificationManager = notificationManager
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
@@ -49,7 +48,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
super.init(initialViewState: .init(userProfile: userSession.clientProxy.userProfilePublisher.value, super.init(initialViewState: .init(userProfile: userSession.clientProxy.userProfilePublisher.value,
bindings: .init(filtersState: .init(userSettings: userSettings))), bindings: .init(filtersState: .init(userSettings: userSession.userSettings))),
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
if userSettings.app.globalSearchEnabled, #available(iOS 26.0, *) { if userSettings.app.globalSearchEnabled, #available(iOS 26.0, *) {
@@ -237,7 +237,6 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -145,7 +145,6 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))))))) roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([])))))))
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -201,7 +201,6 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -133,7 +133,6 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -122,7 +122,6 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -13,7 +13,6 @@ struct JoinRoomScreenCoordinatorParameters {
let source: JoinRoomScreenSource let source: JoinRoomScreenSource
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let userSettings: UserSettings
} }
enum JoinRoomScreenSource { enum JoinRoomScreenSource {
@@ -53,7 +52,6 @@ final class JoinRoomScreenCoordinator: CoordinatorProtocol {
init(parameters: JoinRoomScreenCoordinatorParameters) { init(parameters: JoinRoomScreenCoordinatorParameters) {
viewModel = JoinRoomScreenViewModel(source: parameters.source, viewModel = JoinRoomScreenViewModel(source: parameters.source,
userSettings: parameters.userSettings,
userSession: parameters.userSession, userSession: parameters.userSession,
userIndicatorController: parameters.userIndicatorController) userIndicatorController: parameters.userIndicatorController)
} }
@@ -30,11 +30,10 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
} }
init(source: JoinRoomScreenSource, init(source: JoinRoomScreenSource,
userSettings: UserSettings,
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
userIndicatorController: UserIndicatorControllerProtocol) { userIndicatorController: UserIndicatorControllerProtocol) {
self.source = source self.source = source
self.userSettings = userSettings userSettings = userSession.userSettings
clientProxy = userSession.clientProxy clientProxy = userSession.clientProxy
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
@@ -49,7 +48,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
context.$viewState.map(\.mode) context.$viewState.map(\.mode)
.removeDuplicates() .removeDuplicates()
.sink { mode in .sink { [userSettings = self.userSettings] mode in
switch mode { switch mode {
case .invited: case .invited:
userSettings.app.seenInvites.insert(roomID) userSettings.app.seenInvites.insert(roomID)
@@ -402,8 +402,6 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
self.isSpace = isSpace self.isSpace = isSpace
self.customPreviewName = customPreviewName self.customPreviewName = customPreviewName
let userSettings = UserSettings.mock()
let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars)) let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars))
clientProxy.canJoinRoomWithReturnValue = canJoinRoom clientProxy.canJoinRoomWithReturnValue = canJoinRoom
@@ -455,7 +453,6 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
} }
viewModel = JoinRoomScreenViewModel(source: source, viewModel = JoinRoomScreenViewModel(source: source,
userSettings: userSettings,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
@@ -14,12 +14,10 @@ struct LocationSharingScreenCoordinatorParameters {
let mapURLBuilder: MapTilerURLBuilderProtocol let mapURLBuilder: MapTilerURLBuilderProtocol
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
let timelineController: TimelineControllerProtocol let timelineController: TimelineControllerProtocol
let liveLocationManager: LiveLocationManagerProtocol let userSession: UserSessionProtocol
let userSettings: UserSettings
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let mediaProvider: MediaProviderProtocol
} }
enum LocationSharingScreenCoordinatorAction { enum LocationSharingScreenCoordinatorAction {
@@ -44,11 +42,9 @@ final class LocationSharingScreenCoordinator: CoordinatorProtocol {
mapURLBuilder: parameters.mapURLBuilder, mapURLBuilder: parameters.mapURLBuilder,
roomProxy: parameters.roomProxy, roomProxy: parameters.roomProxy,
timelineController: parameters.timelineController, timelineController: parameters.timelineController,
liveLocationManager: parameters.liveLocationManager, userSession: parameters.userSession,
userSettings: parameters.userSettings,
analytics: parameters.analytics, analytics: parameters.analytics,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController)
mediaProvider: parameters.mediaProvider)
} }
// MARK: - Public // MARK: - Public
@@ -36,16 +36,14 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati
mapURLBuilder: MapTilerURLBuilderProtocol, mapURLBuilder: MapTilerURLBuilderProtocol,
roomProxy: JoinedRoomProxyProtocol, roomProxy: JoinedRoomProxyProtocol,
timelineController: TimelineControllerProtocol, timelineController: TimelineControllerProtocol,
liveLocationManager: LiveLocationManagerProtocol, userSession: UserSessionProtocol,
userSettings: UserSettings,
analytics: AnalyticsServiceProtocol, analytics: AnalyticsServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
mediaProvider: MediaProviderProtocol,
notificationCenter: NotificationCenter = .default) { notificationCenter: NotificationCenter = .default) {
self.roomProxy = roomProxy self.roomProxy = roomProxy
self.timelineController = timelineController self.timelineController = timelineController
self.liveLocationManager = liveLocationManager liveLocationManager = userSession.liveLocationManager
self.userSettings = userSettings userSettings = userSession.userSettings
self.analytics = analytics self.analytics = analytics
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.notificationCenter = notificationCenter self.notificationCenter = notificationCenter
@@ -53,7 +51,7 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati
super.init(initialViewState: .init(interactionMode: interactionMode, super.init(initialViewState: .init(interactionMode: interactionMode,
mapURLBuilder: mapURLBuilder, mapURLBuilder: mapURLBuilder,
ownUserID: roomProxy.ownUserID), ownUserID: roomProxy.ownUserID),
mediaProvider: mediaProvider) mediaProvider: userSession.mediaProvider)
updateUserProfiles(members: roomProxy.membersPublisher.value) updateUserProfiles(members: roomProxy.membersPublisher.value)
setupSubscriptions() setupSubscriptions()
@@ -432,16 +430,14 @@ extension LocationSharingScreenViewModel {
let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID)) let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID))
roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock
let userSettings = UserSettings.mock() let userSession = UserSessionMock(.init())
return LocationSharingScreenViewModel(interactionMode: interactionMode, return LocationSharingScreenViewModel(interactionMode: interactionMode,
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSession.userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: TimelineControllerMock(.init()), timelineController: TimelineControllerMock(.init()),
liveLocationManager: LiveLocationManagerMock(), userSession: userSession,
userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock())
mediaProvider: MediaProviderMock(.init()))
} }
} }
@@ -16,7 +16,6 @@ struct MediaEventsTimelineScreenCoordinatorParameters {
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let mediaPlayerProvider: MediaPlayerProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let userSettings: UserSettings
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let emojiProvider: EmojiProviderProtocol let emojiProvider: EmojiProviderProtocol
let linkMetadataProvider: LinkMetadataProviderProtocol let linkMetadataProvider: LinkMetadataProviderProtocol
@@ -33,8 +33,7 @@ enum SessionVerificationScreenFlow {
struct SessionVerificationScreenCoordinatorParameters { struct SessionVerificationScreenCoordinatorParameters {
let sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol let sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol
let flow: SessionVerificationScreenFlow let flow: SessionVerificationScreenFlow
let userSettings: UserSettings let userSession: UserSessionProtocol
let mediaProvider: MediaProviderProtocol
} }
final class SessionVerificationScreenCoordinator: CoordinatorProtocol { final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
@@ -50,8 +49,7 @@ final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
init(parameters: SessionVerificationScreenCoordinatorParameters) { init(parameters: SessionVerificationScreenCoordinatorParameters) {
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: parameters.sessionVerificationControllerProxy, viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: parameters.sessionVerificationControllerProxy,
flow: parameters.flow, flow: parameters.flow,
userSettings: parameters.userSettings, userSession: parameters.userSession)
mediaProvider: parameters.mediaProvider)
} }
// MARK: - Public // MARK: - Public
@@ -25,8 +25,7 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
init(sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol, init(sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol,
flow: SessionVerificationScreenFlow, flow: SessionVerificationScreenFlow,
userSettings: UserSettings, userSession: UserSessionProtocol,
mediaProvider: MediaProviderProtocol,
verificationState: SessionVerificationScreenStateMachine.State = .initial) { verificationState: SessionVerificationScreenStateMachine.State = .initial) {
self.sessionVerificationControllerProxy = sessionVerificationControllerProxy self.sessionVerificationControllerProxy = sessionVerificationControllerProxy
self.flow = flow self.flow = flow
@@ -34,9 +33,9 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
stateMachine = SessionVerificationScreenStateMachine(state: verificationState) stateMachine = SessionVerificationScreenStateMachine(state: verificationState)
super.init(initialViewState: .init(flow: flow, super.init(initialViewState: .init(flow: flow,
learnMoreURL: userSettings.app.encryptionURL, learnMoreURL: userSession.userSettings.app.encryptionURL,
verificationState: verificationState), verificationState: verificationState),
mediaProvider: mediaProvider) mediaProvider: userSession.mediaProvider)
setupStateMachine() setupStateMachine()
@@ -289,8 +289,7 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview {
flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View { flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View {
let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(), let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(),
flow: flow, flow: flow,
userSettings: .mock(), userSession: UserSessionMock(.init()),
mediaProvider: MediaProviderMock(.init()),
verificationState: state) verificationState: state)
return SessionVerificationScreen(context: viewModel.context) return SessionVerificationScreen(context: viewModel.context)
@@ -15,7 +15,6 @@ struct PinnedEventsTimelineScreenCoordinatorParameters {
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let mediaPlayerProvider: MediaPlayerProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let userSettings: UserSettings
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let emojiProvider: EmojiProviderProtocol let emojiProvider: EmojiProviderProtocol
let linkMetadataProvider: LinkMetadataProviderProtocol let linkMetadataProvider: LinkMetadataProviderProtocol
@@ -46,7 +45,7 @@ final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol {
init(parameters: PinnedEventsTimelineScreenCoordinatorParameters) { init(parameters: PinnedEventsTimelineScreenCoordinatorParameters) {
viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: parameters.roomProxy, viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: parameters.roomProxy,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
userSettings: parameters.userSettings, userSettings: parameters.userSession.userSettings,
analyticsService: parameters.analytics) analyticsService: parameters.analytics)
timelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, timelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy,
timelineController: parameters.timelineController, timelineController: parameters.timelineController,
@@ -12,7 +12,6 @@ import SwiftUI
struct RoomDetailsScreenCoordinatorParameters { struct RoomDetailsScreenCoordinatorParameters {
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let userSettings: UserSettings
let appHooks: AppHooks let appHooks: AppHooks
let analyticsService: AnalyticsServiceProtocol let analyticsService: AnalyticsServiceProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
@@ -54,7 +53,6 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
isSpace = parameters.roomProxy.infoPublisher.value.isSpace isSpace = parameters.roomProxy.infoPublisher.value.isSpace
viewModel = RoomDetailsScreenViewModel(roomProxy: parameters.roomProxy, viewModel = RoomDetailsScreenViewModel(roomProxy: parameters.roomProxy,
userSession: parameters.userSession, userSession: parameters.userSession,
userSettings: parameters.userSettings,
appHooks: parameters.appHooks, appHooks: parameters.appHooks,
analyticsService: parameters.analyticsService, analyticsService: parameters.analyticsService,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
@@ -45,7 +45,6 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
init(roomProxy: JoinedRoomProxyProtocol, init(roomProxy: JoinedRoomProxyProtocol,
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
userSettings: UserSettings,
appHooks: AppHooks, appHooks: AppHooks,
analyticsService: AnalyticsServiceProtocol, analyticsService: AnalyticsServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
@@ -68,7 +67,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
topicSummary: topic?.unattributedStringByReplacingNewlinesWithSpaces(), topicSummary: topic?.unattributedStringByReplacingNewlinesWithSpaces(),
joinedMembersCount: roomProxy.infoPublisher.value.joinedMembersCount, joinedMembersCount: roomProxy.infoPublisher.value.joinedMembersCount,
notificationSettingsState: .loading, notificationSettingsState: .loading,
isNativeCallingEnabled: userSettings.app.nativeCallEnabled, isNativeCallingEnabled: userSession.userSettings.app.nativeCallEnabled,
bindings: .init()) bindings: .init())
super.init(initialViewState: appHooks.roomDetailsScreenHook.update(viewState), super.init(initialViewState: appHooks.roomDetailsScreenHook.update(viewState),
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
@@ -445,7 +445,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -474,7 +473,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -513,7 +511,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)), userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -10,10 +10,8 @@ import SwiftUI
struct SearchScreenCoordinatorParameters { struct SearchScreenCoordinatorParameters {
let roomSummaryProvider: RoomSummaryProviderProtocol let roomSummaryProvider: RoomSummaryProviderProtocol
let clientProxy: ClientProxyProtocol let userSession: UserSessionProtocol
let mediaProvider: MediaProviderProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let userSettings: UserSettings
} }
enum SearchScreenCoordinatorAction { enum SearchScreenCoordinatorAction {
@@ -33,10 +31,8 @@ final class SearchScreenCoordinator: CoordinatorProtocol {
init(parameters: SearchScreenCoordinatorParameters) { init(parameters: SearchScreenCoordinatorParameters) {
viewModel = SearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider, viewModel = SearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider,
clientProxy: parameters.clientProxy, userSession: parameters.userSession,
mediaProvider: parameters.mediaProvider, userIndicatorController: parameters.userIndicatorController)
userIndicatorController: parameters.userIndicatorController,
userSettings: parameters.userSettings)
} }
func start() { func start() {
@@ -33,20 +33,18 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
} }
init(roomSummaryProvider: RoomSummaryProviderProtocol, init(roomSummaryProvider: RoomSummaryProviderProtocol,
clientProxy: ClientProxyProtocol, userSession: UserSessionProtocol,
mediaProvider: MediaProviderProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
userSettings: UserSettings,
initialSearchQuery: String = "", initialSearchQuery: String = "",
initialSearchMode: SearchScreenMode = .rooms) { initialSearchMode: SearchScreenMode = .rooms) {
self.roomSummaryProvider = roomSummaryProvider self.roomSummaryProvider = roomSummaryProvider
self.clientProxy = clientProxy clientProxy = userSession.clientProxy
searchService = clientProxy.searchService searchService = userSession.clientProxy.searchService
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.userSettings = userSettings userSettings = userSession.userSettings
super.init(initialViewState: SearchScreenViewState(bindings: .init(searchQuery: initialSearchQuery, searchMode: initialSearchMode)), super.init(initialViewState: SearchScreenViewState(bindings: .init(searchQuery: initialSearchQuery, searchMode: initialSearchMode)),
mediaProvider: mediaProvider) mediaProvider: userSession.mediaProvider)
roomSummaryProvider.roomListPublisher roomSummaryProvider.roomListPublisher
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
@@ -626,46 +626,35 @@ private final class KeyNavigatingSearchTextField: UISearchTextField {
struct SearchScreen_Previews: PreviewProvider, TestablePreview { struct SearchScreen_Previews: PreviewProvider, TestablePreview {
static let emptyViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let emptyViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(), userSession: UserSessionMock(.init(clientProxy: makeClientProxy())),
mediaProvider: MediaProviderMock(.init()), userIndicatorController: UserIndicatorControllerMock())
userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.mock())
static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(), userSession: UserSessionMock(.init(clientProxy: makeClientProxy())),
mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.mock(),
initialSearchQuery: "John Doe") initialSearchQuery: "John Doe")
static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
clientProxy: makeClientProxy(), userSession: UserSessionMock(.init(clientProxy: makeClientProxy())),
mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation") initialSearchQuery: "Foundation")
static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)), userSession: UserSessionMock(.init(clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)))),
mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation", initialSearchQuery: "Foundation",
initialSearchMode: .messages) initialSearchMode: .messages)
static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)), userSession: UserSessionMock(.init(clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)))),
mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation", initialSearchQuery: "Foundation",
initialSearchMode: .messages) initialSearchMode: .messages)
static let breadcrumbsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let breadcrumbsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(), userSession: UserSessionMock(.init(clientProxy: makeClientProxy(),
mediaProvider: MediaProviderMock(.init()), userSettings: makeUserSettings(breadcrumbs: [.room(roomID: "!room1:matrix.org"),
userIndicatorController: UserIndicatorControllerMock(), .query("Bob"),
userSettings: makeUserSettings(breadcrumbs: [.room(roomID: "!room1:matrix.org"), .room(roomID: "!room5:matrix.org"),
.query("Bob"), .query("Element HR"),
.room(roomID: "!room5:matrix.org"), .query("Alice")]))),
.query("Element HR"), userIndicatorController: UserIndicatorControllerMock())
.query("Alice")]))
static var previews: some View { static var previews: some View {
ElementNavigationStack { ElementNavigationStack {
@@ -11,9 +11,8 @@ import SwiftUI
struct SecurityAndPrivacyScreenCoordinatorParameters { struct SecurityAndPrivacyScreenCoordinatorParameters {
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
let clientProxy: ClientProxyProtocol let userSession: UserSessionProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let appSetting: UserSettings
let appHooks: AppHooks let appHooks: AppHooks
} }
@@ -35,9 +34,8 @@ final class SecurityAndPrivacyScreenCoordinator: CoordinatorProtocol {
init(parameters: SecurityAndPrivacyScreenCoordinatorParameters) { init(parameters: SecurityAndPrivacyScreenCoordinatorParameters) {
viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: parameters.roomProxy, viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: parameters.roomProxy,
clientProxy: parameters.clientProxy, userSession: parameters.userSession,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
userSettings: parameters.appSetting,
appHooks: parameters.appHooks) appHooks: parameters.appHooks)
} }
@@ -24,14 +24,13 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
} }
init(roomProxy: JoinedRoomProxyProtocol, init(roomProxy: JoinedRoomProxyProtocol,
clientProxy: ClientProxyProtocol, userSession: UserSessionProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
userSettings: UserSettings,
appHooks: AppHooks) { appHooks: AppHooks) {
self.roomProxy = roomProxy self.roomProxy = roomProxy
self.clientProxy = clientProxy clientProxy = userSession.clientProxy
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.userSettings = userSettings userSettings = userSession.userSettings
let viewState = SecurityAndPrivacyScreenViewState(accessType: roomProxy.infoPublisher.value.joinRule.toSecurityAndPrivacyRoomAccessType, let viewState = SecurityAndPrivacyScreenViewState(accessType: roomProxy.infoPublisher.value.joinRule.toSecurityAndPrivacyRoomAccessType,
isEncryptionEnabled: roomProxy.infoPublisher.value.isEncrypted, isEncryptionEnabled: roomProxy.infoPublisher.value.isEncrypted,
@@ -233,9 +233,8 @@ struct SecurityAndPrivacyScreen: View {
struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
static let inviteOnlyViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsCreator, static let inviteOnlyViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsCreator,
joinRule: .invite)), joinRule: .invite)),
clientProxy: ClientProxyMock(.init()), userSession: UserSessionMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -243,22 +242,18 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .public, joinRule: .public,
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .public)), joinRule: .public)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let singleSpaceMembersViewModel = { static let singleSpaceMembersViewModel = {
let userSettings = UserSettings.mock()
let space = [SpaceServiceRoom].mockSingleRoom[0] let space = [SpaceServiceRoom].mockSingleRoom[0]
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -266,16 +261,13 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .restricted(rules: [.roomMembership(roomID: space.id)]), joinRule: .restricted(rules: [.roomMembership(roomID: space.id)]),
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))), spaceServiceConfiguration: .init(joinedParentSpaces: [space]))))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
static let multipleSpacesMembersViewModel = { static let multipleSpacesMembersViewModel = {
let userSettings = UserSettings.mock()
let spaces = [SpaceServiceRoom].mockJoinedSpaces let spaces = [SpaceServiceRoom].mockJoinedSpaces
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -283,10 +275,9 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .restricted(rules: spaces.map { .roomMembership(roomID: $0.id) }), joinRule: .restricted(rules: spaces.map { .roomMembership(roomID: $0.id) }),
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))), spaceServiceConfiguration: .init(joinedParentSpaces: spaces))))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
@@ -299,9 +290,9 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .knock, joinRule: .knock,
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
userSettings: userSettings)),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
@@ -316,10 +307,10 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .knockRestricted(rules: [.roomMembership(roomID: space.id)]), joinRule: .knockRestricted(rules: [.roomMembership(roomID: space.id)]),
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
spaceServiceConfiguration: .init(joinedParentSpaces: [space]))), spaceServiceConfiguration: .init(joinedParentSpaces: [space]))),
userSettings: userSettings)),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
@@ -334,10 +325,10 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .knockRestricted(rules: spaces.map { .roomMembership(roomID: $0.id) }), joinRule: .knockRestricted(rules: spaces.map { .roomMembership(roomID: $0.id) }),
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org",
spaceServiceConfiguration: .init(joinedParentSpaces: spaces))), spaceServiceConfiguration: .init(joinedParentSpaces: spaces))),
userSettings: userSettings)),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
}() }()
@@ -347,9 +338,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
members: .allMembersAsCreator, members: .allMembersAsCreator,
joinRule: .public, joinRule: .public,
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static var previews: some View { static var previews: some View {
@@ -15,7 +15,6 @@ struct NotificationSettingsScreenCoordinatorParameters {
let userNotificationCenter: UserNotificationCenterProtocol let userNotificationCenter: UserNotificationCenterProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let isModallyPresented: Bool let isModallyPresented: Bool
let userSettings: UserSettings
} }
enum NotificationSettingsScreenCoordinatorAction { enum NotificationSettingsScreenCoordinatorAction {
@@ -39,9 +38,9 @@ final class NotificationSettingsScreenCoordinator: CoordinatorProtocol {
init(parameters: NotificationSettingsScreenCoordinatorParameters) { init(parameters: NotificationSettingsScreenCoordinatorParameters) {
self.parameters = parameters self.parameters = parameters
viewModel = NotificationSettingsScreenViewModel(userSettings: parameters.userSettings, viewModel = NotificationSettingsScreenViewModel(userSettings: parameters.userSession.userSettings,
userNotificationCenter: parameters.userNotificationCenter, userNotificationCenter: parameters.userNotificationCenter,
notificationToneManager: NotificationToneManager(userSettings: parameters.userSettings), notificationToneManager: NotificationToneManager(userSettings: parameters.userSession.userSettings),
notificationSettingsProxy: parameters.userSession.clientProxy.notificationSettings, notificationSettingsProxy: parameters.userSession.clientProxy.notificationSettings,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
isModallyPresented: parameters.isModallyPresented) isModallyPresented: parameters.isModallyPresented)
@@ -11,7 +11,6 @@ import SwiftUI
struct SettingsScreenCoordinatorParameters { struct SettingsScreenCoordinatorParameters {
let userSession: UserSessionProtocol let userSession: UserSessionProtocol
let userSettings: UserSettings
let isBugReportServiceEnabled: Bool let isBugReportServiceEnabled: Bool
let isInSecondaryWindow: Bool let isInSecondaryWindow: Bool
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
@@ -59,7 +58,6 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
init(parameters: SettingsScreenCoordinatorParameters) { init(parameters: SettingsScreenCoordinatorParameters) {
viewModel = SettingsScreenViewModel(userSession: parameters.userSession, viewModel = SettingsScreenViewModel(userSession: parameters.userSession,
userSettings: parameters.userSettings,
isBugReportServiceEnabled: parameters.isBugReportServiceEnabled, isBugReportServiceEnabled: parameters.isBugReportServiceEnabled,
isInSecondaryWindow: parameters.isInSecondaryWindow, isInSecondaryWindow: parameters.isInSecondaryWindow,
userIndicatorController: parameters.userIndicatorController) userIndicatorController: parameters.userIndicatorController)
@@ -22,8 +22,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
init(userSession: UserSessionProtocol, userSettings: UserSettings, isBugReportServiceEnabled: Bool, isInSecondaryWindow: Bool, userIndicatorController: UserIndicatorControllerProtocol) { init(userSession: UserSessionProtocol, isBugReportServiceEnabled: Bool, isInSecondaryWindow: Bool, userIndicatorController: UserIndicatorControllerProtocol) {
self.userSettings = userSettings userSettings = userSession.userSettings
clientProxy = userSession.clientProxy clientProxy = userSession.clientProxy
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
@@ -313,15 +313,15 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
} }
static func makeViewModel(isBugReportServiceEnabled: Bool = true) -> SettingsScreenViewModel { static func makeViewModel(isBugReportServiceEnabled: Bool = true) -> SettingsScreenViewModel {
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@alice:example.com",
deviceID: "AAAAAAAAAAA",
displayName: "Alice Liddell",
status: .mockFocussing))))
let userSettings = UserSettings.mock() let userSettings = UserSettings.mock()
userSettings.app.multiAccountEnabled = true userSettings.app.multiAccountEnabled = true
userSettings.app.linkNewDeviceEnabled = true userSettings.app.linkNewDeviceEnabled = true
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@alice:example.com",
deviceID: "AAAAAAAAAAA",
displayName: "Alice Liddell",
status: .mockFocussing)),
userSettings: userSettings))
return SettingsScreenViewModel(userSession: userSession, return SettingsScreenViewModel(userSession: userSession,
userSettings: userSettings,
isBugReportServiceEnabled: isBugReportServiceEnabled, isBugReportServiceEnabled: isBugReportServiceEnabled,
isInSecondaryWindow: false, isInSecondaryWindow: false,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -132,7 +132,6 @@ struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview {
canonicalAlias: "#space:matrix.org", canonicalAlias: "#space:matrix.org",
members: members)), members: members)),
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -21,7 +21,6 @@ struct ThreadTimelineScreenCoordinatorParameters {
let linkMetadataProvider: LinkMetadataProviderProtocol let linkMetadataProvider: LinkMetadataProviderProtocol
let completionSuggestionService: CompletionSuggestionServiceProtocol let completionSuggestionService: CompletionSuggestionServiceProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let userSettings: UserSettings
let analytics: AnalyticsServiceProtocol let analytics: AnalyticsServiceProtocol
let composerDraftService: ComposerDraftServiceProtocol let composerDraftService: ComposerDraftServiceProtocol
let timelineControllerFactory: TimelineControllerFactoryProtocol let timelineControllerFactory: TimelineControllerFactoryProtocol
@@ -56,7 +55,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
} }
init(parameters: ThreadTimelineScreenCoordinatorParameters) { init(parameters: ThreadTimelineScreenCoordinatorParameters) {
userSettings = parameters.userSettings userSettings = parameters.userSession.userSettings
viewModel = ThreadTimelineScreenViewModel(roomProxy: parameters.roomProxy, userSession: parameters.userSession) viewModel = ThreadTimelineScreenViewModel(roomProxy: parameters.roomProxy, userSession: parameters.userSession)
@@ -83,7 +82,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
completionSuggestionService: parameters.completionSuggestionService, completionSuggestionService: parameters.completionSuggestionService,
mediaProvider: parameters.userSession.mediaProvider, mediaProvider: parameters.userSession.mediaProvider,
mentionDisplayHelper: ComposerMentionDisplayHelper(timelineContext: timelineViewModel.context), mentionDisplayHelper: ComposerMentionDisplayHelper(timelineContext: timelineViewModel.context),
userSettings: parameters.userSettings, userSettings: parameters.userSession.userSettings,
analyticsService: parameters.analytics, analyticsService: parameters.analytics,
composerDraftService: parameters.composerDraftService) composerDraftService: parameters.composerDraftService)
} }
@@ -81,7 +81,7 @@ nonisolated struct ClientFactory: ClientFactoryProtocol {
func makeNSEClient(credentials: KeychainCredentials, func makeNSEClient(credentials: KeychainCredentials,
roomID: String, roomID: String,
clientSessionDelegate: ClientSessionDelegate, clientSessionDelegate: ClientSessionDelegate,
userSettings: CommonSettingsProtocol, userSettings: UserSettings,
appHooks: AppHooks) async throws -> ClientProtocol { appHooks: AppHooks) async throws -> ClientProtocol {
let homeserverURL = credentials.restorationToken.session.homeserverUrl let homeserverURL = credentials.restorationToken.session.homeserverUrl
@@ -90,10 +90,10 @@ nonisolated struct ClientFactory: ClientFactoryProtocol {
discoverSlidingSync: false, discoverSlidingSync: false,
sessionDelegate: clientSessionDelegate, sessionDelegate: clientSessionDelegate,
appHooks: appHooks, appHooks: appHooks,
enableOnlySignedDeviceIsolationMode: userSettings.enableOnlySignedDeviceIsolationMode, enableOnlySignedDeviceIsolationMode: userSettings.app.enableOnlySignedDeviceIsolationMode,
requestTimeout: 15000, requestTimeout: 15000,
maxRequestRetryTime: 5000, maxRequestRetryTime: 5000,
threadsEnabled: userSettings.threadsEnabled) threadsEnabled: userSettings.app.threadsEnabled)
.systemIsMemoryConstrained() .systemIsMemoryConstrained()
.sqliteStore(config: .init(dataPath: credentials.restorationToken.sessionDirectories.dataPath, .sqliteStore(config: .init(dataPath: credentials.restorationToken.sessionDirectories.dataPath,
cachePath: credentials.restorationToken.sessionDirectories.cachePath) cachePath: credentials.restorationToken.sessionDirectories.cachePath)
@@ -36,6 +36,6 @@ nonisolated protocol ClientFactoryProtocol {
func makeNSEClient(credentials: KeychainCredentials, func makeNSEClient(credentials: KeychainCredentials,
roomID: String, roomID: String,
clientSessionDelegate: ClientSessionDelegate, clientSessionDelegate: ClientSessionDelegate,
userSettings: CommonSettingsProtocol, userSettings: UserSettings,
appHooks: AppHooks) async throws -> ClientProtocol appHooks: AppHooks) async throws -> ClientProtocol
} }
@@ -597,8 +597,7 @@ class MockScreen: Identifiable {
requestDelay: .seconds(5)) requestDelay: .seconds(5))
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy, let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy,
flow: .deviceInitiator, flow: .deviceInitiator,
userSettings: .mock(), userSession: UserSessionMock(.init()))
mediaProvider: MediaProviderMock(.init()))
return SessionVerificationScreenCoordinator(parameters: parameters) return SessionVerificationScreenCoordinator(parameters: parameters)
case .userSessionScreen, .userSessionScreenReply, .userSessionSpacesFlow: case .userSessionScreen, .userSessionScreenReply, .userSessionSpacesFlow:
let userID = "@mock:client.com" let userID = "@mock:client.com"
@@ -647,7 +646,6 @@ class MockScreen: Identifiable {
emojiProvider: EmojiProvider(userSettings: userSession.userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: appMediator, appMediator: appMediator,
userSettings: userSession.userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: analytics, analytics: analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -700,7 +698,6 @@ class MockScreen: Identifiable {
emojiProvider: EmojiProvider(userSettings: userSession.userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSession.userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: analytics, analytics: analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -801,7 +798,6 @@ class MockScreen: Identifiable {
emojiProvider: EmojiProvider(userSettings: userSession.userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSession.userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: analytics, analytics: analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -858,7 +854,6 @@ class MockScreen: Identifiable {
emojiProvider: EmojiProvider(userSettings: userSession.userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSession.userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: analytics, analytics: analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -7,7 +7,7 @@
import UserNotifications import UserNotifications
nonisolated extension CommonSettingsProtocol { nonisolated extension AppSettings {
/// The sound name to use in outgoing notifications. /// The sound name to use in outgoing notifications.
/// Falls back to the default Element X tone if no custom tone has been selected. /// Falls back to the default Element X tone if no custom tone has been selected.
var notificationSoundName: UNNotificationSoundName { var notificationSoundName: UNNotificationSoundName {
+5 -5
View File
@@ -17,7 +17,7 @@ nonisolated protocol NSEUserSessionProtocol {
} }
final nonisolated class NSEUserSession: NSEUserSessionProtocol { final nonisolated class NSEUserSession: NSEUserSessionProtocol {
private let userSettings: CommonSettingsProtocol let userSettings: UserSettings
private let baseClient: ClientProtocol private let baseClient: ClientProtocol
private let notificationClient: NotificationClient private let notificationClient: NotificationClient
private let userID: String private let userID: String
@@ -49,17 +49,17 @@ final nonisolated class NSEUserSession: NSEUserSessionProtocol {
} }
var threadsEnabled: Bool { var threadsEnabled: Bool {
userSettings.threadsEnabled userSettings.app.threadsEnabled
} }
init(credentials: KeychainCredentials, init(credentials: KeychainCredentials,
roomID: String, roomID: String,
clientSessionDelegate: ClientSessionDelegate, clientSessionDelegate: ClientSessionDelegate,
clientFactory: ClientFactoryProtocol = ClientFactory(), clientFactory: ClientFactoryProtocol = ClientFactory(),
userSettings: CommonSettingsProtocol, appSettings: AppSettings,
appHooks: AppHooks) async throws { appHooks: AppHooks) async throws {
userID = credentials.userID userID = credentials.userID
self.userSettings = userSettings userSettings = appSettings.userSettings(for: credentials.userID)
baseClient = try await clientFactory.makeNSEClient(credentials: credentials, baseClient = try await clientFactory.makeNSEClient(credentials: credentials,
roomID: roomID, roomID: roomID,
@@ -75,7 +75,7 @@ final nonisolated class NSEUserSession: NSEUserSessionProtocol {
delegateHandle = try baseClient.setDelegate(delegate: ClientDelegateWrapper()) delegateHandle = try baseClient.setDelegate(delegate: ClientDelegateWrapper())
// Inject the content scanner so the SDK gates the media it downloads whilst building the notification. // Inject the content scanner so the SDK gates the media it downloads whilst building the notification.
if let contentScannerURL = userSettings.contentScannerURL.publisher.value { if let contentScannerURL = userSettings.app.contentScannerURL.publisher.value {
let contentScanner = ContentScanner(scannerUrl: contentScannerURL.absoluteString) let contentScanner = ContentScanner(scannerUrl: contentScannerURL.absoluteString)
await baseClient.setContentScanner(contentScanner: contentScanner) await baseClient.setContentScanner(contentScanner: contentScanner)
} }
+12 -11
View File
@@ -13,7 +13,6 @@ import UserNotifications
nonisolated class NotificationHandler { nonisolated class NotificationHandler {
private let userSession: NSEUserSession private let userSession: NSEUserSession
private let settings: CommonSettingsProtocol
private let contentHandler: (UNNotificationContent) -> Void private let contentHandler: (UNNotificationContent) -> Void
private var notificationContent: UNMutableNotificationContent private var notificationContent: UNMutableNotificationContent
private let tag: String private let tag: String
@@ -23,13 +22,15 @@ nonisolated class NotificationHandler {
/// Whether this handler has already counted its notification towards the app icon badge. /// Whether this handler has already counted its notification towards the app icon badge.
private var hasCountedTowardsBadge = false private var hasCountedTowardsBadge = false
private var userSettings: UserSettings {
userSession.userSettings
}
init(userSession: NSEUserSession, init(userSession: NSEUserSession,
settings: CommonSettingsProtocol,
contentHandler: @escaping (UNNotificationContent) -> Void, contentHandler: @escaping (UNNotificationContent) -> Void,
notificationContent: UNMutableNotificationContent, notificationContent: UNMutableNotificationContent,
tag: String) { tag: String) {
self.userSession = userSession self.userSession = userSession
self.settings = settings
self.contentHandler = contentHandler self.contentHandler = contentHandler
self.notificationContent = notificationContent self.notificationContent = notificationContent
self.tag = tag self.tag = tag
@@ -38,7 +39,7 @@ nonisolated class NotificationHandler {
style: .plain) style: .plain)
notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: eventStringBuilder, notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: eventStringBuilder,
notificationSoundName: settings.notificationSoundName, notificationSoundName: userSession.userSettings.app.notificationSoundName,
userSession: userSession) userSession: userSession)
} }
@@ -55,7 +56,7 @@ nonisolated class NotificationHandler {
case .processedShouldDiscard, .unsupportedShouldDiscard: case .processedShouldDiscard, .unsupportedShouldDiscard:
discardNotification() discardNotification()
case .shouldDisplay: case .shouldDisplay:
if settings.hideQuietNotificationAlerts, !notificationItemProxy.isNoisy { if userSettings.app.hideQuietNotificationAlerts, !notificationItemProxy.isNoisy {
discardNotification() discardNotification()
return return
} }
@@ -79,20 +80,20 @@ nonisolated class NotificationHandler {
private func deliverNotification() { private func deliverNotification() {
notificationContent.badge = NSNumber(value: incrementBadgeCount()) notificationContent.badge = NSNumber(value: incrementBadgeCount())
MXLog.info("\(tag) Delivering notification, new badge value: \(settings.lastKnownBadgeCount)") MXLog.info("\(tag) Delivering notification, new badge value: \(userSettings.app.lastKnownBadgeCount)")
contentHandler(notificationContent) contentHandler(notificationContent)
} }
private func incrementBadgeCount() -> Int { private func incrementBadgeCount() -> Int {
// `handleTimeExpiration` can deliver a notification this handler already delivered. // `handleTimeExpiration` can deliver a notification this handler already delivered.
guard !hasCountedTowardsBadge else { guard !hasCountedTowardsBadge else {
return settings.lastKnownBadgeCount return userSettings.app.lastKnownBadgeCount
} }
hasCountedTowardsBadge = true hasCountedTowardsBadge = true
settings.lastKnownBadgeCount += 1 userSettings.app.lastKnownBadgeCount += 1
return settings.lastKnownBadgeCount return userSettings.app.lastKnownBadgeCount
} }
private func discardNotification() { private func discardNotification() {
@@ -100,7 +101,7 @@ nonisolated class NotificationHandler {
let content = UNMutableNotificationContent() let content = UNMutableNotificationContent()
// Nothing new is shown to the user, so leave the badge where the app last put it. // Nothing new is shown to the user, so leave the badge where the app last put it.
content.badge = NSNumber(value: settings.lastKnownBadgeCount) content.badge = NSNumber(value: userSettings.app.lastKnownBadgeCount)
MXLog.info("\(tag) New badge value: \(content.badge?.stringValue ?? "nil")") MXLog.info("\(tag) New badge value: \(content.badge?.stringValue ?? "nil")")
contentHandler(content) contentHandler(content)
@@ -135,7 +136,7 @@ nonisolated class NotificationHandler {
if let targetNotification = deliveredNotifications.first(where: { $0.request.content.eventID == redactedEventID }) { if let targetNotification = deliveredNotifications.first(where: { $0.request.content.eventID == redactedEventID }) {
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [targetNotification.request.identifier]) UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [targetNotification.request.identifier])
settings.lastKnownBadgeCount = max(0, settings.lastKnownBadgeCount - 1) userSettings.app.lastKnownBadgeCount = max(0, userSettings.app.lastKnownBadgeCount - 1)
} }
return .processedShouldDiscard return .processedShouldDiscard
+11 -12
View File
@@ -63,7 +63,7 @@ actor NotificationServiceExtensionActor {
private static let firstNotificationThreshold: TimeInterval = 15 * 60 private static let firstNotificationThreshold: TimeInterval = 15 * 60
private let settings: CommonSettingsProtocol private let appSettings: AppSettings
private let appHooks: AppHooks private let appHooks: AppHooks
/// This is nonisolated just because the expire function needs to be served ASAP so we should not call it from a Task, however this is /// This is nonisolated just because the expire function needs to be served ASAP so we should not call it from a Task, however this is
@@ -82,7 +82,7 @@ actor NotificationServiceExtensionActor {
guard let userDefaults = TrackedUserDefaults(suiteName: AppSettings.suiteName) else { guard let userDefaults = TrackedUserDefaults(suiteName: AppSettings.suiteName) else {
fatalError("Catastrophic error retrieving user defaults for \(AppSettings.suiteName)") fatalError("Catastrophic error retrieving user defaults for \(AppSettings.suiteName)")
} }
settings = AppSettings(store: userDefaults) appSettings = AppSettings(store: userDefaults)
appHooks = AppHooks() appHooks = AppHooks()
appHooks.setUp() appHooks.setUp()
@@ -96,10 +96,10 @@ actor NotificationServiceExtensionActor {
if !BootDetectionManager.isDeviceLockedAfterReboot(containerURL: URL.appGroupContainerDirectory) { if !BootDetectionManager.isDeviceLockedAfterReboot(containerURL: URL.appGroupContainerDirectory) {
Self.targetConfiguration.withLock { state in Self.targetConfiguration.withLock { state in
guard state == nil else { return } guard state == nil else { return }
state = Target.nse.configure(logLevel: settings.logLevel, state = Target.nse.configure(logLevel: appSettings.logLevel,
traceLogPacks: settings.traceLogPacks, traceLogPacks: appSettings.traceLogPacks,
sentryURL: nil, sentryURL: nil,
rageshakeURL: settings.bugReportRageshakeURL, rageshakeURL: appSettings.bugReportRageshakeURL,
appHooks: appHooks) appHooks: appHooks)
} }
} }
@@ -161,7 +161,7 @@ actor NotificationServiceExtensionActor {
} }
let homeserverURL = credentials.restorationToken.session.homeserverUrl let homeserverURL = credentials.restorationToken.session.homeserverUrl
await appHooks.remoteSettingsHook.loadCache(forHomeserver: homeserverURL, applyingTo: settings) await appHooks.remoteSettingsHook.loadCache(forHomeserver: homeserverURL, applyingTo: appSettings)
guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else { guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
return contentHandler(request.content) return contentHandler(request.content)
@@ -177,11 +177,10 @@ actor NotificationServiceExtensionActor {
let userSession = try await NSEUserSession(credentials: credentials, let userSession = try await NSEUserSession(credentials: credentials,
roomID: roomID, roomID: roomID,
clientSessionDelegate: keychainController, clientSessionDelegate: keychainController,
userSettings: settings, appSettings: appSettings,
appHooks: appHooks) appHooks: appHooks)
notificationHandler = NotificationHandler(userSession: userSession, notificationHandler = NotificationHandler(userSession: userSession,
settings: settings,
contentHandler: contentHandler, contentHandler: contentHandler,
notificationContent: mutableContent, notificationContent: mutableContent,
tag: tag) tag: tag)
@@ -221,10 +220,10 @@ actor NotificationServiceExtensionActor {
return false return false
} }
guard let lastKnownBootTime = settings.lastNotificationBootTime else { guard let lastKnownBootTime = appSettings.lastNotificationBootTime else {
// Assume a missing boot time indicates a fresh installation… // Assume a missing boot time indicates a fresh installation…
// So store the current boot time but let the notification through. // So store the current boot time but let the notification through.
settings.lastNotificationBootTime = currentBootTime appSettings.lastNotificationBootTime = currentBootTime
return false return false
} }
@@ -233,7 +232,7 @@ actor NotificationServiceExtensionActor {
} }
// This is the first notification since boot, store the boot time. // This is the first notification since boot, store the boot time.
settings.lastNotificationBootTime = currentBootTime appSettings.lastNotificationBootTime = currentBootTime
// At this point it becomes a trade-off. Once the device has been powered on for a long enough amount // At this point it becomes a trade-off. Once the device has been powered on for a long enough amount
// of time it is a reasonable assumption that the device has now connected to a network and that any // of time it is a reasonable assumption that the device has now connected to a network and that any
@@ -258,7 +257,7 @@ actor NotificationServiceExtensionActor {
let content = UNMutableNotificationContent() let content = UNMutableNotificationContent()
content.body = L10n.notificationReceivedWhileOfflineIos content.body = L10n.notificationReceivedWhileOfflineIos
content.sound = settings.notificationSound content.sound = appSettings.notificationSound
let request = UNNotificationRequest(identifier: Self.receivedWhileOfflineNotificationID, content: content, trigger: nil) let request = UNNotificationRequest(identifier: Self.receivedWhileOfflineNotificationID, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request) UNUserNotificationCenter.current().add(request)
@@ -12,7 +12,7 @@ import SwiftUI
class ShareExtensionViewController: UIViewController { class ShareExtensionViewController: UIViewController {
private static var targetConfiguration: Target.ConfigurationResult? private static var targetConfiguration: Target.ConfigurationResult?
private let userSettings: CommonSettingsProtocol = { private let appSettings: AppSettings = {
guard let userDefaults = TrackedUserDefaults(suiteName: AppSettings.suiteName) else { guard let userDefaults = TrackedUserDefaults(suiteName: AppSettings.suiteName) else {
fatalError("Catastrophic error retrieving user defaults for \(AppSettings.suiteName)") fatalError("Catastrophic error retrieving user defaults for \(AppSettings.suiteName)")
} }
@@ -33,10 +33,10 @@ class ShareExtensionViewController: UIViewController {
appHooks.setUp() appHooks.setUp()
if Self.targetConfiguration == nil { if Self.targetConfiguration == nil {
Self.targetConfiguration = Target.shareExtension.configure(logLevel: userSettings.logLevel, Self.targetConfiguration = Target.shareExtension.configure(logLevel: appSettings.logLevel,
traceLogPacks: userSettings.traceLogPacks, traceLogPacks: appSettings.traceLogPacks,
sentryURL: nil, sentryURL: nil,
rageshakeURL: userSettings.bugReportRageshakeURL, rageshakeURL: appSettings.bugReportRageshakeURL,
appHooks: appHooks) appHooks: appHooks)
} }
@@ -50,7 +50,7 @@ class ShareExtensionViewController: UIViewController {
if let credentials = keychainController.restorationTokens().first { if let credentials = keychainController.restorationTokens().first {
let homeserverURL = credentials.restorationToken.session.homeserverUrl let homeserverURL = credentials.restorationToken.session.homeserverUrl
appHooks.remoteSettingsHook.loadCache(forHomeserver: homeserverURL, applyingTo: userSettings) appHooks.remoteSettingsHook.loadCache(forHomeserver: homeserverURL, applyingTo: appSettings)
} else { } else {
// We should really show a different state when there isn't a logged in user, but for now this is fine. // We should really show a different state when there isn't a logged in user, but for now this is fine.
MXLog.error("Not logged in, launching app to show the authentication flow.") MXLog.error("Not logged in, launching app to show the authentication flow.")
@@ -29,8 +29,6 @@ struct ChatsTabFlowCoordinatorTests {
} }
init() async throws { init() async throws {
let userSettings = UserSettings.mock()
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
timelineControllerFactory = TimelineControllerFactoryMock(.init()) timelineControllerFactory = TimelineControllerFactoryMock(.init())
@@ -38,14 +36,14 @@ struct ChatsTabFlowCoordinatorTests {
notificationManager = NotificationManagerMock() notificationManager = NotificationManagerMock()
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let flowParameters = CommonFlowParameters(userSession: userSession,
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
emojiProvider: EmojiProvider(userSettings: userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -84,7 +84,7 @@ final class CreateRoomScreenViewModelTests {
userID: "@a:b.com", userID: "@a:b.com",
spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()]))) spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()])))
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) } clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
userSession = UserSessionMock(.init(clientProxy: clientProxy)) userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
userSettings.app.knockingEnabled = true userSettings.app.knockingEnabled = true
let viewModel = CreateRoomScreenViewModel(isSpace: true, let viewModel = CreateRoomScreenViewModel(isSpace: true,
spaceSelectionMode: .none, spaceSelectionMode: .none,
@@ -92,7 +92,6 @@ final class CreateRoomScreenViewModelTests {
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
self.viewModel = viewModel self.viewModel = viewModel
@@ -335,7 +334,7 @@ final class CreateRoomScreenViewModelTests {
userID: "@a:b.com")) userID: "@a:b.com"))
clientProxy.spaceService = spaceService clientProxy.spaceService = spaceService
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) } clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
userSession = UserSessionMock(.init(clientProxy: clientProxy)) userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
userSettings.app.knockingEnabled = true userSettings.app.knockingEnabled = true
let viewModel = CreateRoomScreenViewModel(isSpace: isSpace, let viewModel = CreateRoomScreenViewModel(isSpace: isSpace,
spaceSelectionMode: spacesSelectionMode, spaceSelectionMode: spacesSelectionMode,
@@ -343,7 +342,6 @@ final class CreateRoomScreenViewModelTests {
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
self.viewModel = viewModel self.viewModel = viewModel
} }
@@ -588,7 +588,7 @@ final class HomeScreenViewModelTests {
break break
} }
let userSession = UserSessionMock(.init(clientProxy: clientProxy)) let userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
if let securityStatePublisher { if let securityStatePublisher {
userSession.sessionSecurityStatePublisher = securityStatePublisher userSession.sessionSecurityStatePublisher = securityStatePublisher
} }
@@ -597,7 +597,6 @@ final class HomeScreenViewModelTests {
viewModel = HomeScreenViewModel(userSession: userSession, viewModel = HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: notificationManager, notificationManager: notificationManager,
@@ -237,8 +237,7 @@ final class JoinRoomScreenViewModelTests {
} }
viewModel = JoinRoomScreenViewModel(source: .generic(roomID: "1", via: []), viewModel = JoinRoomScreenViewModel(source: .generic(roomID: "1", via: []),
userSettings: userSettings, userSession: UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings)),
userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -417,17 +417,15 @@ struct LocationSharingScreenViewModelTests {
let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers)) let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers))
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
let userSettings = UserSettings.mock() let userSession = UserSessionMock(.init())
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil), viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil),
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSession.userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
liveLocationManager: LiveLocationManagerMock(.init()), userSession: userSession,
userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock())
mediaProvider: MediaProviderMock(.init()))
// Initially no annotations and no map center since sender and share are both nil. // Initially no annotations and no map center since sender and share are both nil.
#expect(context.viewState.annotations.isEmpty) #expect(context.viewState.annotations.isEmpty)
@@ -636,11 +634,9 @@ struct LocationSharingScreenViewModelTests {
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: JoinedRoomProxyMock(.init(members: members)), roomProxy: JoinedRoomProxyMock(.init(members: members)),
timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)), timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)),
liveLocationManager: liveLocationManagerMock, userSession: UserSessionMock(.init(userSettings: userSettings, liveLocationManager: liveLocationManagerMock)),
userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock())
mediaProvider: MediaProviderMock(.init()))
viewModel.state.bindings.isLocationAuthorized = true viewModel.state.bindings.isLocationAuthorized = true
} }
@@ -664,11 +660,9 @@ struct LocationSharingScreenViewModelTests {
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value,
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
liveLocationManager: LiveLocationManagerMock(.init()), userSession: UserSessionMock(.init(userSettings: userSettings)),
userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock())
mediaProvider: MediaProviderMock(.init()))
} }
private func makeLiveLocationShare(userID: String, latitude: Double = 0.0, longitude: Double = 0.0) -> LiveLocationShare { private func makeLiveLocationShare(userID: String, latitude: Double = 0.0, longitude: Double = 0.0) -> LiveLocationShare {
@@ -30,7 +30,6 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -44,7 +43,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -65,7 +63,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -87,7 +84,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -146,7 +142,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -168,7 +163,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -201,7 +195,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -233,7 +226,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -266,7 +258,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -300,7 +291,6 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -318,7 +308,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -367,7 +356,6 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -403,7 +391,6 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -439,7 +426,6 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -460,7 +446,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -481,7 +466,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -500,7 +484,6 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error") notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error")
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -709,7 +692,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -731,7 +713,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -755,7 +736,6 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -779,7 +759,6 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -807,7 +786,6 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -522,14 +522,13 @@ final class RoomFlowCoordinatorTests {
"1" "1"
} }
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings)),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
emojiProvider: EmojiProvider(userSettings: userSettings), emojiProvider: EmojiProvider(userSettings: userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -51,16 +51,15 @@ struct RoomMembersFlowCoordinatorTests {
let clientProxy = ClientProxyMock(.init()) let clientProxy = ClientProxyMock(.init())
clientProxy.directRoomForUserIDReturnValue = .success(nil) clientProxy.directRoomForUserIDReturnValue = .success(nil)
let userSettings = UserSettings.mock() let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: userSession,
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()), timelineControllerFactory: TimelineControllerFactoryMock(.init()),
emojiProvider: EmojiProvider(userSettings: userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -57,10 +57,8 @@ struct SearchScreenViewModelTests {
userSettings = UserSettings.mock() userSettings = UserSettings.mock()
viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
clientProxy: clientProxy, userSession: UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings)),
mediaProvider: MediaProviderMock(.init()), userIndicatorController: userIndicatorController)
userIndicatorController: userIndicatorController,
userSettings: userSettings)
} }
@Test @Test
@@ -468,12 +468,13 @@ final class SecurityAndPrivacyScreenViewModelTests {
roomProxy.updateJoinRuleReturnValue = .success(()) roomProxy.updateJoinRuleReturnValue = .success(())
roomProxy.updateRoomDirectoryVisibilityReturnValue = .success(()) roomProxy.updateRoomDirectoryVisibilityReturnValue = .success(())
let clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org",
spaceServiceConfiguration: .init(topLevelSpaces: topLevelSpaces,
joinedParentSpaces: joinedParentSpaces)))
viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: roomProxy, viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: roomProxy,
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", userSession: UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings)),
spaceServiceConfiguration: .init(topLevelSpaces: topLevelSpaces,
joinedParentSpaces: joinedParentSpaces))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: userSettings,
appHooks: AppHooks()) appHooks: AppHooks())
} }
} }
@@ -21,8 +21,7 @@ struct SessionVerificationViewModelTests {
sessionVerificationController = SessionVerificationControllerProxyMock.configureMock() sessionVerificationController = SessionVerificationControllerProxyMock.configureMock()
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController, viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController,
flow: .deviceInitiator, flow: .deviceInitiator,
userSettings: .mock(), userSession: UserSessionMock(.init()))
mediaProvider: MediaProviderMock(.init()))
context = viewModel.context context = viewModel.context
} }
@@ -202,8 +202,7 @@ struct SettingsScreenViewModelTests {
private mutating func setupViewModel(status: UserStatus = .init(), userSettings: UserSettings = .mock()) { private mutating func setupViewModel(status: UserStatus = .init(), userSettings: UserSettings = .mock()) {
clientProxy = ClientProxyMock(.init(userID: "", status: status)) clientProxy = ClientProxyMock(.init(userID: "", status: status))
viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)), viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings)),
userSettings: userSettings,
isBugReportServiceEnabled: true, isBugReportServiceEnabled: true,
isInSecondaryWindow: false, isInSecondaryWindow: false,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -48,16 +48,15 @@ struct UserSessionFlowCoordinatorTests {
appMediator.networkMonitor = networkMonitor appMediator.networkMonitor = networkMonitor
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
let userSettings = UserSettings.mock() let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: userSession,
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()), timelineControllerFactory: TimelineControllerFactoryMock(.init()),
emojiProvider: EmojiProvider(userSettings: userSettings), emojiProvider: EmojiProvider(userSettings: userSession.userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: appMediator, appMediator: appMediator,
userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,