mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
AppSettings are Mockable (#5589)
* create DependenciesProtocol and replace ServiceLocator registration with it replace mocking calls for ServiceLocator to Dependencies replace ServiceLocator with instance level calls replace ServiceLocator configs with TestDependencies config in Tests replace servicelocator usage in analytics service replace remaining ServiceLocator calls in unit tests that depended on the UnitTestAppCoordinator configuration with per suite dependencies instances fix swiftlint warning remove remaining references to ServiceLocator make dependencies properties consistent in tests delete Dependencies and DependenciesProtocol fix whitespace modifications updates from PR feedback a pass over converting AppSettings and AnalyticsService test instance properties to per test instantiation fix a missed PR feedback Sync up after rebase create DependenciesProtocol and replace ServiceLocator registration with it replace mocking calls for ServiceLocator to Dependencies replace ServiceLocator with instance level calls replace ServiceLocator configs with TestDependencies config in Tests replace servicelocator usage in analytics service replace remaining ServiceLocator calls in unit tests that depended on the UnitTestAppCoordinator configuration with per suite dependencies instances fix swiftlint warning remove remaining references to ServiceLocator make dependencies properties consistent in tests delete Dependencies and DependenciesProtocol * AppSettings is instance level mockable now * replace mocked and preview usages of reset + AppSettings global init with AppSettings(store: UserDefaultsMock()) * AppSettings.UserDefaultsKeys is now a RawRep struct, making it extensible * update tests with new AppSettings so it builds * update remaining AppSettings test/mock inits * AppSettings.UserDefaultsKey conformed to ExpressibleByStringLiteral * addressed issues found in first pass ai review * update AppSettings instantiations after rebase * fix accessibility tests coordinator after rebase * Rename to VolatileUserDefaults * AppSettings init uses mandatory parameter * Revert UserDefaultsKey to enum * Add TrackedUserDefaults to be able to reset the defaults object * Added volatile static func to AppSettings * Use .volatile() static func instead of full init * review fixups * Resolve build issues after rebase * updated enterprise module * remove the static reset settings call from the preview tests --------- Co-authored-by: Mauro Romito <mauro.romito@element.io>
This commit is contained in:
@@ -40,8 +40,7 @@ class AccessibilityTestsAppCoordinator: AppCoordinatorProtocol {
|
||||
|
||||
MXLog.configure(currentTarget: "accessibility-tests")
|
||||
|
||||
AppSettings.configureWithSuiteName("io.element.elementx.accessibilitytests")
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
guard let name = ProcessInfo.accessibilityViewID,
|
||||
let previewType = TestablePreviewsDictionary.dictionary[name] else {
|
||||
|
||||
@@ -78,7 +78,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
let networkMonitor = NetworkMonitor()
|
||||
appMediator = AppMediator(windowManager: windowManager, networkMonitor: networkMonitor)
|
||||
|
||||
let appSettings = appHooks.appSettingsHook.configure(AppSettings())
|
||||
guard let userDefaults = TrackedUserDefaults(suiteName: AppSettings.suiteName) else {
|
||||
fatalError("Catastrophic error retrieving user defaults for \(AppSettings.suiteName)")
|
||||
}
|
||||
let appSettings = appHooks.appSettingsHook.configure(AppSettings(store: userDefaults))
|
||||
self.appSettings = appSettings
|
||||
|
||||
targetConfiguration = Target.mainApp.configure(logLevel: appSettings.logLevel,
|
||||
@@ -93,7 +96,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
MXLog.info("\(appName) \(appVersion) (\(appBuild))")
|
||||
|
||||
if ProcessInfo.processInfo.environment["RESET_APP_SETTINGS"].map(Bool.init) == true {
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings.resetAllSettings()
|
||||
}
|
||||
|
||||
self.appDelegate = appDelegate
|
||||
@@ -544,7 +547,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
/// - Parameter includingSettings: Whether to additionally wipe the user's app settings too.
|
||||
private func wipeUserData(includingSettings: Bool = false) {
|
||||
if includingSettings {
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings.resetAllSettings()
|
||||
appLockFlowCoordinator.appLockService.disable()
|
||||
}
|
||||
userSessionStore.reset()
|
||||
@@ -830,7 +833,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
userSessionStore.logout(userSession: userSession)
|
||||
tearDownUserSession()
|
||||
|
||||
AppSettings.resetSessionSpecificSettings()
|
||||
appSettings.resetSessionSpecificSettings()
|
||||
appHooks.remoteSettingsHook.reset(appSettings)
|
||||
|
||||
// Reset analytics
|
||||
|
||||
@@ -37,7 +37,7 @@ enum AppBuildType {
|
||||
///
|
||||
/// State is persisted in `UserDefaults`, which is thread-safe per Apple's documentation, hence `@unchecked`.
|
||||
final class AppSettings: @unchecked Sendable {
|
||||
private enum UserDefaultsKeys: String {
|
||||
fileprivate enum UserDefaultsKeys: String, PreferenceKeyable {
|
||||
case lastVersionLaunched
|
||||
case seenInvites
|
||||
case hasSeenNewSoundBanner
|
||||
@@ -94,10 +94,10 @@ final class AppSettings: @unchecked Sendable {
|
||||
case developerOptionsEnabled
|
||||
}
|
||||
|
||||
private nonisolated(unsafe) static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
|
||||
static let suiteName: String = InfoPlistReader.main.appGroupIdentifier
|
||||
|
||||
/// UserDefaults to be used on reads and writes. `UserDefaults` is thread-safe per Apple's documentation.
|
||||
private nonisolated(unsafe) static var store: UserDefaults! = UserDefaults(suiteName: suiteName)
|
||||
/// UserDefaults to be used on reads and writes.
|
||||
private let store: UserDefaultsProtocol
|
||||
|
||||
static var appBuildType: AppBuildType {
|
||||
#if DEBUG
|
||||
@@ -112,26 +112,16 @@ final class AppSettings: @unchecked Sendable {
|
||||
#endif
|
||||
}
|
||||
|
||||
static func resetAllSettings() {
|
||||
func resetAllSettings() {
|
||||
MXLog.warning("Resetting the AppSettings.")
|
||||
store.removePersistentDomain(forName: suiteName)
|
||||
store.reset()
|
||||
}
|
||||
|
||||
static func resetSessionSpecificSettings() {
|
||||
func resetSessionSpecificSettings() {
|
||||
MXLog.warning("Resetting the user session specific AppSettings.")
|
||||
store.removeObject(forKey: UserDefaultsKeys.hasRunIdentityConfirmationOnboarding.rawValue)
|
||||
}
|
||||
|
||||
static func configureWithSuiteName(_ name: String) {
|
||||
suiteName = name
|
||||
|
||||
guard let userDefaults = UserDefaults(suiteName: name) else {
|
||||
fatalError("Fail to load shared UserDefaults")
|
||||
}
|
||||
|
||||
store = userDefaults
|
||||
}
|
||||
|
||||
// MARK: - Hooks
|
||||
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
@@ -182,17 +172,17 @@ final class AppSettings: @unchecked Sendable {
|
||||
/// The last known version of the app that was launched on this device, which is
|
||||
/// used to detect when migrations should be run. When `nil` the app may have been
|
||||
/// deleted between runs so should clear data in the shared container and keychain.
|
||||
@UserPreference(key: UserDefaultsKeys.lastVersionLaunched, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var lastVersionLaunched: String?
|
||||
|
||||
/// The Set of room identifiers of invites that the user already saw in the invites list.
|
||||
/// This Set is being used to implement badges for unread invites.
|
||||
@UserPreference(key: UserDefaultsKeys.seenInvites, defaultValue: [], storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var seenInvites: Set<String>
|
||||
|
||||
/// Defaults to `true` for new users, and we use a migration to set it to `false` for existing users.
|
||||
@UserPreference(key: UserDefaultsKeys.hasSeenNewSoundBanner, defaultValue: true, storageType: .userDefaults(store))
|
||||
var hasSeenNewSoundBanner
|
||||
@UserPreference
|
||||
var hasSeenNewSoundBanner: Bool
|
||||
|
||||
/// The initial set of account providers shown to the user in the authentication flow.
|
||||
///
|
||||
@@ -236,7 +226,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
/// **Note:** This property isn't overridable as it in unexpected for forks to come across the error (or to even have a "Pro" app).
|
||||
let elementProAppStoreURL: URL = "https://apps.apple.com/app/element-pro-for-work/id6502951615"
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.appAppearance, defaultValue: .system, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var appAppearance: AppAppearance
|
||||
|
||||
// MARK: - Security
|
||||
@@ -248,7 +238,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
/// Any codes that the user isn't allowed to use for their PIN.
|
||||
let appLockPINCodeBlockList = ["0000", "1234"]
|
||||
/// The number of attempts the user has made to unlock the app with a PIN code (resets when unlocked).
|
||||
@UserPreference(key: UserDefaultsKeys.appLockNumberOfPINAttempts, defaultValue: 0, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var appLockNumberOfPINAttempts: Int
|
||||
|
||||
// MARK: - Authentication
|
||||
@@ -287,33 +277,33 @@ final class AppSettings: @unchecked Sendable {
|
||||
pushGatewayBaseURL.appending(path: "_matrix/push/v1/notify")
|
||||
}
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.enableNotifications, defaultValue: true, storageType: .userDefaults(store))
|
||||
var enableNotifications
|
||||
@UserPreference
|
||||
var enableNotifications: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.enableInAppNotifications, defaultValue: true, storageType: .userDefaults(store))
|
||||
var enableInAppNotifications
|
||||
@UserPreference
|
||||
var enableInAppNotifications: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hideQuietNotificationAlerts, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hideQuietNotificationAlerts
|
||||
@UserPreference
|
||||
var hideQuietNotificationAlerts: Bool
|
||||
|
||||
/// Tag describing which set of device specific rules a pusher executes.
|
||||
@UserPreference(key: UserDefaultsKeys.pusherProfileTag, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var pusherProfileTag: String?
|
||||
|
||||
/// The device's last boot time as recorded by the NSE.
|
||||
@UserPreference(key: UserDefaultsKeys.lastNotificationBootTime, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var lastNotificationBootTime: TimeInterval?
|
||||
|
||||
/// The sound played when delivering noisy notifications. If nil, use the ElementX default
|
||||
@UserPreference(key: UserDefaultsKeys.selectedNotificationTone, defaultValue: nil, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var selectedNotificationTone: NotificationTone?
|
||||
|
||||
// MARK: - Logging
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: LogLevel.info, storageType: .userDefaults(store))
|
||||
var logLevel
|
||||
@UserPreference
|
||||
var logLevel: LogLevel
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.traceLogPacks, defaultValue: [], storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var traceLogPacks: Set<TraceLogPack>
|
||||
|
||||
// MARK: - Bug report
|
||||
@@ -341,46 +331,46 @@ final class AppSettings: @unchecked Sendable {
|
||||
}
|
||||
|
||||
/// Whether the user has opted in to send analytics.
|
||||
@UserPreference(key: UserDefaultsKeys.analyticsConsentState, defaultValue: AnalyticsConsentState.unknown, storageType: .userDefaults(store))
|
||||
var analyticsConsentState
|
||||
@UserPreference
|
||||
var analyticsConsentState: AnalyticsConsentState
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hasRunNotificationPermissionsOnboarding, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hasRunNotificationPermissionsOnboarding
|
||||
@UserPreference
|
||||
var hasRunNotificationPermissionsOnboarding: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hasRunIdentityConfirmationOnboarding, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hasRunIdentityConfirmationOnboarding
|
||||
@UserPreference
|
||||
var hasRunIdentityConfirmationOnboarding: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hasRequestedLocationAlwaysLocationAuthorization, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hasRequestedLocationAlwaysLocationAuthorization
|
||||
@UserPreference
|
||||
var hasRequestedLocationAlwaysLocationAuthorization: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storageType: .userDefaults(store))
|
||||
var frequentlyUsedSystemEmojis
|
||||
@UserPreference
|
||||
var frequentlyUsedSystemEmojis: [FrequentlyUsedEmoji]
|
||||
|
||||
// MARK: - Live Location
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.liveLocationSharingTimeoutDatesByRoomID, defaultValue: [String: LiveLocationSession](), storageType: .userDefaults(store))
|
||||
var liveLocationSharingSessionsByRoomID
|
||||
@UserPreference
|
||||
var liveLocationSharingSessionsByRoomID: [String: LiveLocationSession]
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.liveLocationMinimumDistanceUpdate, defaultValue: 10, storageType: .userDefaults(store))
|
||||
var liveLocationMinimumDistanceUpdate
|
||||
@UserPreference
|
||||
var liveLocationMinimumDistanceUpdate: Int
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.liveLocationDisclaimerDisplayed, defaultValue: false, storageType: .userDefaults(store))
|
||||
var liveLocationDisclaimerDisplayed
|
||||
@UserPreference
|
||||
var liveLocationDisclaimerDisplayed: Bool
|
||||
|
||||
// MARK: - Home Screen
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.roomListActivityVisibility, defaultValue: .current, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var roomListActivityVisibility: RoomListActivityVisibility
|
||||
|
||||
// MARK: - Room Screen
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.viewSourceEnabled, defaultValue: appBuildType == .debug, storageType: .userDefaults(store))
|
||||
var viewSourceEnabled
|
||||
@UserPreference
|
||||
var viewSourceEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.optimizeMediaUploads, defaultValue: true, storageType: .userDefaults(store))
|
||||
var optimizeMediaUploads
|
||||
@UserPreference
|
||||
var optimizeMediaUploads: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.voiceMessagePlaybackSpeed, defaultValue: AudioPlaybackSpeed.default, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var voiceMessagePlaybackSpeed: AudioPlaybackSpeed
|
||||
|
||||
/// Whether or not to show a warning on the media caption composer so the user knows
|
||||
@@ -399,7 +389,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
let elementCallPosthogAPIKey = "phc_rXGHx9vDmyEvyRxPziYtdVIv0ahEv8A9uLWFcCi1WcU"
|
||||
let elementCallPosthogSentryDSN = "https://3bd2f95ba5554d4497da7153b552ffb5@sentry.tools.element.io/41"
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.elementCallBaseURLOverride, defaultValue: nil, storageType: .userDefaults(store))
|
||||
@UserPreference
|
||||
var elementCallBaseURLOverride: URL?
|
||||
|
||||
// MARK: - Users
|
||||
@@ -417,51 +407,111 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
// MARK: - Presence
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.sharePresence, defaultValue: true, storageType: .userDefaults(store))
|
||||
var sharePresence
|
||||
@UserPreference
|
||||
var sharePresence: Bool
|
||||
|
||||
// MARK: - Feature Flags
|
||||
|
||||
/// Others
|
||||
@UserPreference(key: UserDefaultsKeys.fuzzyRoomListSearchEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var fuzzyRoomListSearchEnabled
|
||||
@UserPreference
|
||||
var fuzzyRoomListSearchEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.lowPriorityFilterEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var lowPriorityFilterEnabled
|
||||
@UserPreference
|
||||
var lowPriorityFilterEnabled: Bool
|
||||
|
||||
/// Configuration to enable only signed device isolation mode for crypto. In this mode only devices signed by their owner will be considered in e2ee rooms.
|
||||
@UserPreference(key: UserDefaultsKeys.enableOnlySignedDeviceIsolationMode, defaultValue: false, storageType: .userDefaults(store))
|
||||
var enableOnlySignedDeviceIsolationMode
|
||||
@UserPreference
|
||||
var enableOnlySignedDeviceIsolationMode: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var knockingEnabled
|
||||
@UserPreference
|
||||
var knockingEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.threadsEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var threadsEnabled
|
||||
@UserPreference
|
||||
var threadsEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.roomThreadListEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var roomThreadListEnabled
|
||||
@UserPreference
|
||||
var roomThreadListEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.focusEventOnNotificationTap, defaultValue: false, storageType: .userDefaults(store))
|
||||
var focusEventOnNotificationTap
|
||||
@UserPreference
|
||||
var focusEventOnNotificationTap: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.linkPreviewsEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var linkPreviewsEnabled
|
||||
@UserPreference
|
||||
var linkPreviewsEnabled: Bool
|
||||
|
||||
@UserPreference
|
||||
var jumpToReadMarkerEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.jumpToReadMarkerEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var jumpToReadMarkerEnabled
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.linkNewDeviceEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var linkNewDeviceEnabled
|
||||
@UserPreference
|
||||
var linkNewDeviceEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.automaticBackPaginationEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var automaticBackPaginationEnabled
|
||||
@UserPreference
|
||||
var automaticBackPaginationEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.clientPausingAndResumingEnabled, defaultValue: appBuildType != .release, storageType: .volatile)
|
||||
var clientPausingAndResumingEnabled
|
||||
@UserPreference
|
||||
var clientPausingAndResumingEnabled: Bool
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.developerOptionsEnabled, defaultValue: appBuildType != .release, storageType: .userDefaults(store))
|
||||
var developerOptionsEnabled
|
||||
@UserPreference
|
||||
var developerOptionsEnabled: Bool
|
||||
|
||||
init(store: UserDefaultsProtocol) {
|
||||
// UserDefaults to be used on reads and writes.
|
||||
self.store = store
|
||||
|
||||
_lastVersionLaunched = UserPreference(key: .lastVersionLaunched, storage: store)
|
||||
_seenInvites = UserPreference(key: .seenInvites, defaultValue: [], storage: store)
|
||||
_hasSeenNewSoundBanner = UserPreference(key: .hasSeenNewSoundBanner, defaultValue: true, storage: store)
|
||||
_appAppearance = UserPreference(key: .appAppearance, defaultValue: .system, storage: store)
|
||||
_appLockNumberOfPINAttempts = UserPreference(key: .appLockNumberOfPINAttempts, defaultValue: 0, storage: store)
|
||||
_enableNotifications = UserPreference(key: .enableNotifications, defaultValue: true, storage: store)
|
||||
_enableInAppNotifications = UserPreference(key: .enableInAppNotifications, defaultValue: true, storage: store)
|
||||
_hideQuietNotificationAlerts = UserPreference(key: .hideQuietNotificationAlerts, defaultValue: false, storage: store)
|
||||
_pusherProfileTag = UserPreference(key: .pusherProfileTag, storage: store)
|
||||
_lastNotificationBootTime = UserPreference(key: .lastNotificationBootTime, storage: store)
|
||||
_selectedNotificationTone = UserPreference(key: .selectedNotificationTone, storage: store)
|
||||
_logLevel = UserPreference(key: .logLevel, defaultValue: LogLevel.info, storage: store)
|
||||
_traceLogPacks = UserPreference(key: .traceLogPacks, defaultValue: [], storage: store)
|
||||
_analyticsConsentState = UserPreference(key: .analyticsConsentState, defaultValue: AnalyticsConsentState.unknown, storage: store)
|
||||
_hasRunNotificationPermissionsOnboarding = UserPreference(key: .hasRunNotificationPermissionsOnboarding, defaultValue: false, storage: store)
|
||||
_hasRunIdentityConfirmationOnboarding = UserPreference(key: .hasRunIdentityConfirmationOnboarding, defaultValue: false, storage: store)
|
||||
_hasRequestedLocationAlwaysLocationAuthorization = UserPreference(key: .hasRequestedLocationAlwaysLocationAuthorization, defaultValue: false, storage: store)
|
||||
_frequentlyUsedSystemEmojis = UserPreference(key: .frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storage: store)
|
||||
_liveLocationSharingSessionsByRoomID = UserPreference(key: .liveLocationSharingTimeoutDatesByRoomID, defaultValue: [String: LiveLocationSession](), storage: store)
|
||||
_liveLocationMinimumDistanceUpdate = UserPreference(key: .liveLocationMinimumDistanceUpdate, defaultValue: 10, storage: store)
|
||||
_liveLocationDisclaimerDisplayed = UserPreference(key: .liveLocationDisclaimerDisplayed, defaultValue: false, storage: store)
|
||||
_roomListActivityVisibility = UserPreference(key: .roomListActivityVisibility, defaultValue: .current, storage: store)
|
||||
_viewSourceEnabled = UserPreference(key: .viewSourceEnabled, defaultValue: Self.appBuildType == .debug, storage: store)
|
||||
_optimizeMediaUploads = UserPreference(key: .optimizeMediaUploads, defaultValue: true, storage: store)
|
||||
_voiceMessagePlaybackSpeed = UserPreference(key: .voiceMessagePlaybackSpeed, defaultValue: AudioPlaybackSpeed.default, storage: store)
|
||||
_elementCallBaseURLOverride = UserPreference(key: .elementCallBaseURLOverride, defaultValue: nil, storage: store)
|
||||
_sharePresence = UserPreference(key: .sharePresence, defaultValue: true, storage: store)
|
||||
_fuzzyRoomListSearchEnabled = UserPreference(key: .fuzzyRoomListSearchEnabled, defaultValue: false, storage: store)
|
||||
_lowPriorityFilterEnabled = UserPreference(key: .lowPriorityFilterEnabled, defaultValue: false, storage: store)
|
||||
_enableOnlySignedDeviceIsolationMode = UserPreference(key: .enableOnlySignedDeviceIsolationMode, defaultValue: false, storage: store)
|
||||
_knockingEnabled = UserPreference(key: .knockingEnabled, defaultValue: false, storage: store)
|
||||
_threadsEnabled = UserPreference(key: .threadsEnabled, defaultValue: false, storage: store)
|
||||
_roomThreadListEnabled = UserPreference(key: .roomThreadListEnabled, defaultValue: false, storage: store)
|
||||
_focusEventOnNotificationTap = UserPreference(key: .focusEventOnNotificationTap, defaultValue: false, storage: store)
|
||||
_linkPreviewsEnabled = UserPreference(key: .linkPreviewsEnabled, defaultValue: false, storage: store)
|
||||
_jumpToReadMarkerEnabled = UserPreference(key: .jumpToReadMarkerEnabled, defaultValue: false, storage: store)
|
||||
_linkNewDeviceEnabled = UserPreference(key: .linkNewDeviceEnabled, defaultValue: false, storage: store)
|
||||
_automaticBackPaginationEnabled = UserPreference(key: .automaticBackPaginationEnabled, defaultValue: false, storage: store)
|
||||
_clientPausingAndResumingEnabled = UserPreference(key: .clientPausingAndResumingEnabled, defaultValue: Self.appBuildType != .release, storage: VolatileUserDefaults())
|
||||
_developerOptionsEnabled = UserPreference(key: .developerOptionsEnabled, defaultValue: Self.appBuildType != .release, storage: store)
|
||||
}
|
||||
|
||||
static func volatile() -> AppSettings {
|
||||
AppSettings(store: VolatileUserDefaults())
|
||||
}
|
||||
}
|
||||
|
||||
extension AppSettings: CommonSettingsProtocol { }
|
||||
|
||||
private extension UserPreference {
|
||||
convenience init(key: AppSettings.UserDefaultsKeys, defaultValue: T, storage backingStorage: UserDefaultsProtocol, mode: Mode = .localOverRemote) {
|
||||
self.init(key: key as any PreferenceKeyable, defaultValue: defaultValue, storage: backingStorage, mode: mode)
|
||||
}
|
||||
|
||||
convenience init(key: AppSettings.UserDefaultsKeys, storage: UserDefaultsProtocol, mode: Mode = .localOverRemote) where T: ExpressibleByNilLiteral {
|
||||
self.init(key: key as any PreferenceKeyable, defaultValue: nil, storage: storage, mode: mode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
final class TrackedUserDefaults: UserDefaults, UserDefaultsProtocol {
|
||||
private let lock = NSLock()
|
||||
|
||||
private nonisolated(unsafe) var _trackedSuites: [String] = []
|
||||
private(set) var trackedSuites: [String] {
|
||||
get { lock.withLock { _trackedSuites } }
|
||||
set { lock.withLock { _trackedSuites = newValue } }
|
||||
}
|
||||
|
||||
override init?(suiteName suitename: String?) {
|
||||
if let suitename {
|
||||
lock.lock()
|
||||
_trackedSuites = [suitename]
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
super.init(suiteName: suitename)
|
||||
}
|
||||
|
||||
override func addSuite(named suiteName: String) {
|
||||
trackedSuites.append(suiteName)
|
||||
super.addSuite(named: suiteName)
|
||||
}
|
||||
|
||||
override func removeSuite(named suiteName: String) {
|
||||
trackedSuites.removeAll { $0 == suiteName }
|
||||
super.removeSuite(named: suiteName)
|
||||
}
|
||||
|
||||
func resetRegisteredDomains() {
|
||||
lock.withLock {
|
||||
for suite in _trackedSuites {
|
||||
removePersistentDomain(forName: suite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reset() {
|
||||
resetRegisteredDomains()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright 2025 Element Creations Ltd.
|
||||
// Copyright 2022-2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol UserDefaultsProtocol: AnyObject {
|
||||
func data(forKey key: String) -> Data?
|
||||
func object(forKey key: String) -> Any?
|
||||
func removeObject(forKey key: String)
|
||||
func set(_ value: Any?, forKey key: String)
|
||||
|
||||
func reset()
|
||||
}
|
||||
@@ -46,11 +46,11 @@ final class UserPreference<T: Codable> {
|
||||
/// - defaultValue: The default value to use if no stored value exists or if `forceDefault` is `true`.
|
||||
/// - keyedStorage: The storage instance where the value is saved.
|
||||
/// - forceDefault: A publisher that determines whether the default value should always be used. Defaults to publish `false`. Useful in the context of remote settings that need to override the local value.
|
||||
init(key: String,
|
||||
init(key: any PreferenceKeyable,
|
||||
defaultValue: T,
|
||||
keyedStorage: any KeyedStorage<T>,
|
||||
mode: Mode) {
|
||||
self.key = key
|
||||
self.key = key.rawValue
|
||||
self.defaultValue = defaultValue
|
||||
self.keyedStorage = keyedStorage
|
||||
self.mode = mode
|
||||
@@ -95,37 +95,21 @@ final class UserPreference<T: Codable> {
|
||||
// MARK: - UserPreference convenience initializers
|
||||
|
||||
extension UserPreference {
|
||||
enum StorageType {
|
||||
case userDefaults(UserDefaults)
|
||||
case volatile
|
||||
}
|
||||
|
||||
convenience init(key: String, defaultValue: T, storageType: StorageType, mode: Mode = .localOverRemote) {
|
||||
let storage: any KeyedStorage<T>
|
||||
|
||||
switch storageType {
|
||||
case .userDefaults(let userDefaults):
|
||||
storage = UserDefaultsStorage(userDefaults: userDefaults)
|
||||
case .volatile:
|
||||
storage = [String: T]()
|
||||
}
|
||||
|
||||
convenience init(key: any PreferenceKeyable, defaultValue: T, storage backingStorage: UserDefaultsProtocol, mode: Mode = .localOverRemote) {
|
||||
let storage: any KeyedStorage<T> = UserDefaultsStorage(userDefaults: backingStorage)
|
||||
|
||||
self.init(key: key, defaultValue: defaultValue, keyedStorage: storage, mode: mode)
|
||||
}
|
||||
|
||||
convenience init<R: RawRepresentable>(key: R, defaultValue: T, storageType: StorageType, mode: Mode = .localOverRemote) where R.RawValue == String {
|
||||
self.init(key: key.rawValue, defaultValue: defaultValue, storageType: storageType, mode: mode)
|
||||
}
|
||||
|
||||
convenience init(key: String, storageType: StorageType, mode: Mode = .localOverRemote) where T: ExpressibleByNilLiteral {
|
||||
self.init(key: key, defaultValue: nil, storageType: storageType, mode: mode)
|
||||
}
|
||||
|
||||
convenience init<R: RawRepresentable>(key: R, storageType: StorageType, mode: Mode = .localOverRemote) where R: RawRepresentable, R.RawValue == String, T: ExpressibleByNilLiteral {
|
||||
self.init(key: key.rawValue, storageType: storageType, mode: mode)
|
||||
convenience init(key: any PreferenceKeyable, storage: UserDefaultsProtocol, mode: Mode = .localOverRemote) where T: ExpressibleByNilLiteral {
|
||||
self.init(key: key, defaultValue: nil, storage: storage, mode: mode)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Keys
|
||||
|
||||
protocol PreferenceKeyable: RawRepresentable where RawValue == String { }
|
||||
|
||||
// MARK: - Storage
|
||||
|
||||
protocol KeyedStorage<Value> {
|
||||
@@ -139,9 +123,9 @@ protocol KeyedStorage<Value> {
|
||||
/// When used with a `Value` that conforms to `PlistRepresentable` the Codable encode/decode
|
||||
/// phase is skipped, and values are stored natively in the plist.
|
||||
final class UserDefaultsStorage<Value: Codable>: KeyedStorage {
|
||||
private let userDefaults: UserDefaults
|
||||
private let userDefaults: UserDefaultsProtocol
|
||||
|
||||
init(userDefaults: UserDefaults) {
|
||||
init(userDefaults: UserDefaultsProtocol) {
|
||||
self.userDefaults = userDefaults
|
||||
}
|
||||
|
||||
@@ -183,7 +167,7 @@ final class UserDefaultsStorage<Value: Codable>: KeyedStorage {
|
||||
userDefaults.removeObject(forKey: key)
|
||||
} else {
|
||||
let encodedValue = try? JSONEncoder().encode(value)
|
||||
userDefaults.setValue(encodedValue, forKey: key)
|
||||
userDefaults.set(encodedValue, forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public final class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
|
||||
private let lock = NSLock()
|
||||
|
||||
private nonisolated(unsafe) var _storage: [String: Any]
|
||||
public private(set) var storage: [String: Any] {
|
||||
get { lock.withLock { _storage } }
|
||||
set { lock.withLock { _storage = newValue } }
|
||||
}
|
||||
|
||||
public init(initialValues: [String: Any] = [:]) {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
|
||||
_storage = initialValues
|
||||
}
|
||||
|
||||
public func data(forKey key: String) -> Data? {
|
||||
storage[key] as? Data
|
||||
}
|
||||
|
||||
public func object(forKey key: String) -> Any? {
|
||||
storage[key]
|
||||
}
|
||||
|
||||
public func removeObject(forKey key: String) {
|
||||
storage.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
public func set(_ value: Any?, forKey key: String) {
|
||||
storage[key] = value
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
storage = [:]
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ private struct VisualListItemLabelStyle: LabelStyle {
|
||||
// MARK: - Previews
|
||||
|
||||
struct VisualListItem_Previews: PreviewProvider, TestablePreview {
|
||||
static let strings = AnalyticsPromptScreenStrings(termsURL: AppSettings().analyticsTermsURL)
|
||||
static let strings = AnalyticsPromptScreenStrings(termsURL: AppSettings.volatile().analyticsTermsURL)
|
||||
|
||||
static var testImage1: some View {
|
||||
Image(systemName: "circle")
|
||||
|
||||
@@ -161,7 +161,7 @@ struct LoginScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let viewModel = LoginScreenViewModel(authenticationService: authenticationService,
|
||||
loginHint: nil,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analytics: AnalyticsServiceMock.default)
|
||||
|
||||
if withCredentials {
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ struct ServerConfirmationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
ServerConfirmationScreenViewModel(authenticationService: AuthenticationService.mock,
|
||||
mode: mode,
|
||||
authenticationFlow: flow,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ struct ServerSelection_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
let viewModel = ServerSelectionScreenViewModel(authenticationService: authenticationService,
|
||||
authenticationFlow: .login,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
viewModel.context.homeserverAddress = homeserverAddress
|
||||
if homeserverAddress == "thisisbad" {
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ struct AuthenticationClassicAppAccountView_Previews: PreviewProvider { // Not Te
|
||||
provisioningParameters: nil,
|
||||
isBugReportServiceEnabled: false,
|
||||
appMediator: AppMediatorMock(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@ struct AuthenticationStartScreen_Previews: PreviewProvider, TestablePreview {
|
||||
provisioningParameters: provisionedServerName.map { .init(accountProvider: $0, loginHint: nil) },
|
||||
isBugReportServiceEnabled: true,
|
||||
appMediator: AppMediatorMock(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ struct CallScreen_Previews: PreviewProvider {
|
||||
colorScheme: .light),
|
||||
allowPictureInPicture: false,
|
||||
appHooks: AppHooks(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default)
|
||||
}()
|
||||
|
||||
|
||||
@@ -446,8 +446,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
isSpace: Bool = false,
|
||||
selectionMode: CreateRoomScreenSpaceSelectionMode = .editableSpacesList(preSelectedSpace: nil),
|
||||
isAliasAvailable: Bool = true) -> CreateRoomScreenViewModel {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.knockingEnabled = isKnockingEnabled
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(userIDServerName: "example.org",
|
||||
|
||||
@@ -67,7 +67,8 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil),
|
||||
shouldShowCancelButton: false,
|
||||
|
||||
@@ -103,7 +103,7 @@ struct EmojiPickerScreen: View {
|
||||
struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = EmojiPickerScreenViewModel(itemID: .randomEvent,
|
||||
selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(appSettings: AppSettings()),
|
||||
emojiProvider: EmojiProvider(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController())
|
||||
|
||||
static var previews: some View {
|
||||
@@ -116,7 +116,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
|
||||
struct EmojiPickerScreenSheet_Previews: PreviewProvider {
|
||||
static let viewModel = EmojiPickerScreenViewModel(itemID: .randomEvent,
|
||||
selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(appSettings: AppSettings()),
|
||||
emojiProvider: EmojiProvider(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController())
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
+2
-2
@@ -59,10 +59,10 @@ struct RoomListFiltersEmptyStateView_Previews: PreviewProvider, TestablePreview
|
||||
VStack(spacing: 24) {
|
||||
ForEach(RoomListFilter.allCases) { filter in
|
||||
RoomListFiltersEmptyStateView(state: .init(activeFilters: [filter],
|
||||
appSettings: AppSettings()))
|
||||
appSettings: .volatile()))
|
||||
}
|
||||
RoomListFiltersEmptyStateView(state: .init(activeFilters: [.people, .favourites],
|
||||
appSettings: AppSettings()))
|
||||
appSettings: .volatile()))
|
||||
}
|
||||
.padding(.bottom)
|
||||
.previewLayout(.sizeThatFits)
|
||||
|
||||
@@ -90,10 +90,10 @@ struct RoomListFiltersView: View {
|
||||
|
||||
struct RoomListFiltersView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
RoomListFiltersView(state: .constant(.init(appSettings: AppSettings())))
|
||||
RoomListFiltersView(state: .constant(.init(appSettings: .volatile())))
|
||||
RoomListFiltersView(state: .constant(.init(activeFilters: [.rooms, .favourites],
|
||||
appSettings: AppSettings())))
|
||||
appSettings: .volatile())))
|
||||
RoomListFiltersView(state: .constant(.init(activeFilters: [.lowPriority],
|
||||
appSettings: AppSettings())))
|
||||
appSettings: .volatile())))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
@@ -145,7 +145,7 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
|
||||
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([])))))))
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
@@ -202,7 +202,7 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
@@ -134,7 +134,7 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
@@ -255,7 +255,7 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ struct InviteUsersConfirmationSheetView_Previews: PreviewProvider, TestablePrevi
|
||||
isSkippable: true,
|
||||
userDiscoveryService: UserDiscoveryServiceMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
|
||||
viewModel.state.usersToConfirm = [.mockAlice, .mockCharlie, .mockBob, .mockDan]
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
|
||||
isSkippable: isSkippable,
|
||||
userDiscoveryService: userDiscoveryService,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
|
||||
if let searchQuery {
|
||||
viewModel.context.searchQuery = searchQuery
|
||||
|
||||
@@ -403,7 +403,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
|
||||
self.isSpace = isSpace
|
||||
self.customPreviewName = customPreviewName
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars))
|
||||
clientProxy.canJoinRoomWithReturnValue = canJoinRoom
|
||||
|
||||
@@ -64,11 +64,8 @@ struct LabsScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct LabsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return LabsScreenViewModel(labsOptions: AppSettings())
|
||||
}()
|
||||
|
||||
static let viewModel = LabsScreenViewModel(labsOptions: AppSettings.volatile())
|
||||
|
||||
static var previews: some View {
|
||||
ElementNavigationStack {
|
||||
LabsScreen(context: viewModel.context)
|
||||
|
||||
@@ -390,7 +390,7 @@ extension LocationSharingScreenViewModel {
|
||||
roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock
|
||||
|
||||
return LocationSharingScreenViewModel(interactionMode: interactionMode,
|
||||
mapURLBuilder: AppSettings().mapTilerConfiguration,
|
||||
mapURLBuilder: AppSettings.volatile().mapTilerConfiguration,
|
||||
roomProxy: roomProxy,
|
||||
timelineController: MockTimelineController(),
|
||||
liveLocationManager: LiveLocationManagerMock(),
|
||||
|
||||
+1
-1
@@ -310,7 +310,7 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
MockTimelineController.mediaGallery
|
||||
}
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
|
||||
timelineController: timelineController,
|
||||
userSession: UserSessionMock(.init()),
|
||||
|
||||
+1
-1
@@ -370,7 +370,7 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview {
|
||||
title: "App Icon.png",
|
||||
isRoomEncrypted: true,
|
||||
shouldShowCaptionWarning: true,
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: AppSettings()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController(),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
+1
-1
@@ -102,6 +102,6 @@ struct AnalyticsPromptScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
static func makeViewModel(showTerms: Bool = true) -> AnalyticsPromptScreenViewModel {
|
||||
AnalyticsPromptScreenViewModel(termsURL: showTerms ? AppSettings().analyticsTermsURL : nil)
|
||||
AnalyticsPromptScreenViewModel(termsURL: showTerms ? AppSettings.volatile().analyticsTermsURL : nil)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userSession.sessionSecurityStatePublisher = CurrentValuePublisher<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: recoveryState))
|
||||
|
||||
return IdentityConfirmationScreenViewModel(userSession: userSession,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -289,7 +289,7 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview {
|
||||
flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View {
|
||||
let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(),
|
||||
flow: flow,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
verificationState: state)
|
||||
|
||||
|
||||
+3
-2
@@ -68,14 +68,15 @@ struct PinnedEventsTimelineScreen: View {
|
||||
struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default)
|
||||
|
||||
static let emptyTimelineViewModel: TimelineViewModel = {
|
||||
let timelineController = MockTimelineController(timelineKind: .pinned)
|
||||
timelineController.timelineItems = []
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
|
||||
timelineController: timelineController,
|
||||
userSession: UserSessionMock(.init()),
|
||||
|
||||
@@ -177,7 +177,7 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return RoomDetailsEditScreenViewModel(roomProxy: roomProxy,
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: AppSettings()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: .volatile()),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
|
||||
private static func makeSimpleRoomViewModel() -> RoomDetailsScreenViewModel {
|
||||
@@ -452,7 +452,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
|
||||
private static func makeDMViewModel(verificationState: UserIdentityVerificationState) -> RoomDetailsScreenViewModel {
|
||||
@@ -490,6 +490,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,6 +241,6 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
analytics: AnalyticsServiceMock.default,
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,7 +826,7 @@ extension ComposerToolbarViewModel {
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
composerDraftService: ComposerDraftServiceMock(.init()))
|
||||
viewModel.state.bindings.composerFocused = focused
|
||||
|
||||
@@ -81,7 +81,7 @@ struct RoomAttachmentPicker_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = makeViewModel()
|
||||
|
||||
static func makeViewModel() -> ComposerToolbarViewModel {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
|
||||
wysiwygViewModel: WysiwygComposerViewModel(),
|
||||
|
||||
@@ -461,7 +461,7 @@ extension RoomScreenViewModel {
|
||||
roomProxy: roomProxyMock,
|
||||
initialSelectedPinnedEventID: nil,
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
appHooks: appHooks,
|
||||
analyticsService: AnalyticsServiceMock.default,
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
@@ -362,7 +362,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
||||
powerLevelsConfiguration: .init(canUserSendMessage: canSendMessage)))
|
||||
let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
userSession: UserSessionMock(.init()),
|
||||
|
||||
+33
-50
@@ -229,40 +229,30 @@ struct SecurityAndPrivacyScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let inviteOnlyViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsCreator,
|
||||
joinRule: .invite)),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
static let inviteOnlyViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsCreator,
|
||||
joinRule: .invite)),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: .volatile())
|
||||
|
||||
static let publicViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: .volatile())
|
||||
|
||||
static let publicNoAddressViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: .volatile())
|
||||
|
||||
static let singleSpaceMembersViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
let space = [SpaceServiceRoom].mockSingleRoom[0]
|
||||
|
||||
@@ -278,8 +268,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let multipleSpacesMembersViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
let spaces = [SpaceServiceRoom].mockJoinedSpaces
|
||||
|
||||
@@ -295,8 +284,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let askToJoinViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.knockingEnabled = true
|
||||
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
@@ -310,8 +298,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let singleAskToJoinSpaceMembersViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.knockingEnabled = true
|
||||
|
||||
let space = [SpaceServiceRoom].mockSingleRoom[0]
|
||||
@@ -328,8 +315,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let multipleAskToJoinSpacesMembersViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.knockingEnabled = true
|
||||
|
||||
let spaces = [SpaceServiceRoom].mockJoinedSpaces
|
||||
@@ -345,18 +331,15 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
appSettings: appSettings)
|
||||
}()
|
||||
|
||||
static let publicSpaceViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isSpace: true,
|
||||
isEncrypted: false,
|
||||
canonicalAlias: "#space:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
static let publicSpaceViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isSpace: true,
|
||||
isEncrypted: false,
|
||||
canonicalAlias: "#space:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: .volatile())
|
||||
|
||||
static var previews: some View {
|
||||
ElementNavigationStack {
|
||||
|
||||
+1
-2
@@ -161,8 +161,7 @@ private extension AppAppearance {
|
||||
|
||||
struct AdvancedSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
return AdvancedSettingsScreenViewModel(advancedSettings: appSettings,
|
||||
analytics: AnalyticsServiceMock.default,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ struct AnalyticsSettingsScreen: View {
|
||||
|
||||
struct AnalyticsSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
let viewModel = AnalyticsSettingsScreenViewModel(appSettings: appSettings,
|
||||
analytics: AnalyticsServiceMock.default)
|
||||
AnalyticsSettingsScreen(context: viewModel.context)
|
||||
|
||||
+2
-2
@@ -249,8 +249,8 @@ private extension Set<TraceLogPack> {
|
||||
// MARK: - Previews
|
||||
|
||||
struct DeveloperOptionsScreen_Previews: PreviewProvider {
|
||||
static let viewModel = DeveloperOptionsScreenViewModel(developerOptions: AppSettings(),
|
||||
elementCallBaseURL: AppSettings().elementCallBaseURL,
|
||||
static let viewModel = DeveloperOptionsScreenViewModel(developerOptions: AppSettings.volatile(),
|
||||
elementCallBaseURL: AppSettings.volatile().elementCallBaseURL,
|
||||
appHooks: AppHooks(),
|
||||
clientProxy: ClientProxyMock(.init()))
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ struct LegalInformationScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct LegalInformationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = LegalInformationScreenViewModel(appSettings: AppSettings())
|
||||
static let viewModel = LegalInformationScreenViewModel(appSettings: .volatile())
|
||||
static var previews: some View {
|
||||
LegalInformationScreen(context: viewModel.context)
|
||||
}
|
||||
|
||||
+2
-2
@@ -264,7 +264,7 @@ struct NotificationSettingsScreen: View {
|
||||
|
||||
struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel: NotificationSettingsScreenViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
let notificationCenter = UserNotificationCenterMock()
|
||||
notificationCenter.authorizationStatusReturnValue = .notDetermined
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
@@ -292,7 +292,7 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let viewModelConfigurationMismatch: NotificationSettingsScreenViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
let notificationCenter = UserNotificationCenterMock()
|
||||
notificationCenter.authorizationStatusReturnValue = .notDetermined
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
|
||||
@@ -277,7 +277,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com",
|
||||
deviceID: "AAAAAAAAAAA"))))
|
||||
return SettingsScreenViewModel(userSession: userSession,
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
||||
isInSecondaryWindow: false)
|
||||
}
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ struct UserDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||
UserDetailsEditScreenViewModel(userSession: UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@stefan:matrix.org",
|
||||
canChangeAvatar: canChangeProfile,
|
||||
canChangeDisplayName: canChangeProfile)))),
|
||||
mediaUploadingPreprocessor: .init(appSettings: AppSettings()),
|
||||
mediaUploadingPreprocessor: .init(appSettings: .volatile()),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
@@ -144,8 +144,7 @@ struct SpacesScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
static func makeViewModel(isEmpty: Bool = false) -> SpacesScreenViewModel {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
let clientProxy = ClientProxyMock(.init())
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(topLevelSpaces: isEmpty ? [] : .mockJoinedSpaces))
|
||||
|
||||
@@ -87,7 +87,7 @@ struct JoinRoomByAddressView_Previews: PreviewProvider, TestablePreview {
|
||||
analytics: AnalyticsServiceMock.default,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userDiscoveryService: userDiscoveryService,
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
@@ -154,7 +154,7 @@ struct StartChatScreen: View {
|
||||
|
||||
struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
let userDiscoveryService = UserDiscoveryServiceMock()
|
||||
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
|
||||
|
||||
@@ -1121,7 +1121,8 @@ extension TimelineViewModel {
|
||||
clientProxyMock.roomSummaryForIdentifierReturnValue = .mock(id: "!room:matrix.org", name: "Room", canonicalAlias: "#room:matrix.org")
|
||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview room", predecessor: hasPredecessor ? .init(roomId: UUID().uuidString) : nil))
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
|
||||
|
||||
@@ -342,7 +342,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
|
||||
isViewSourceEnabled: true,
|
||||
areThreadsEnabled: true,
|
||||
timelineKind: .live,
|
||||
emojiProvider: EmojiProvider(appSettings: AppSettings()))
|
||||
emojiProvider: EmojiProvider(appSettings: .volatile()))
|
||||
guard let actions = provider.makeActions() else { return nil }
|
||||
|
||||
if var textItem = item as? TextRoomTimelineItem {
|
||||
|
||||
@@ -45,7 +45,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
|
||||
]
|
||||
let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members))
|
||||
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
|
||||
@@ -334,7 +334,7 @@ private extension TimelineItemKeyForwarder {
|
||||
|
||||
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel: TimelineViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.threadsEnabled = true
|
||||
|
||||
let roomProxy = JoinedRoomProxyMock(.init())
|
||||
@@ -353,7 +353,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
||||
}()
|
||||
|
||||
static let viewModelWithPins: TimelineViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
appSettings.threadsEnabled = true
|
||||
|
||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"]))
|
||||
|
||||
@@ -80,7 +80,8 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
|
||||
]
|
||||
|
||||
static let viewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)),
|
||||
timelineController: MockTimelineController(),
|
||||
userSession: UserSessionMock(.init()),
|
||||
|
||||
+2
-1
@@ -90,7 +90,8 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
|
||||
static let focussedEventID = "RoomTimelineItemFixtures.default.5"
|
||||
static let composerViewModel = ComposerToolbarViewModel.mock()
|
||||
static let timelineViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
focussedEventID: focussedEventID,
|
||||
timelineController: MockTimelineController(),
|
||||
|
||||
@@ -153,7 +153,8 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
|
||||
static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
|
||||
static let composerViewModel = ComposerToolbarViewModel.mock()
|
||||
static let timelineViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
userSession: UserSessionMock(.init()),
|
||||
|
||||
@@ -148,6 +148,6 @@ struct UserProfileScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
|
||||
userIndicatorController: UserIndicatorControllerMock.default,
|
||||
analytics: AnalyticsServiceMock.default,
|
||||
appSettings: AppSettings())
|
||||
appSettings: .volatile())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ extension AuthenticationService {
|
||||
encryptionKeyProvider: EncryptionKeyProvider(),
|
||||
classicAppManager: classicAppManager,
|
||||
clientFactory: AuthenticationClientFactoryMock(configuration: .init()),
|
||||
appSettings: AppSettings(),
|
||||
appSettings: .volatile(),
|
||||
appHooks: AppHooks())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,7 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, SecureWindowManagerDelegate
|
||||
|
||||
MXLog.configure(currentTarget: "uitests")
|
||||
|
||||
AppSettings.configureWithSuiteName("io.element.elementx.uitests")
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings = AppSettings()
|
||||
appSettings = AppSettings.volatile()
|
||||
|
||||
let analyticsClient = AnalyticsClientMock()
|
||||
analyticsClient.isRunning = false
|
||||
|
||||
@@ -18,9 +18,6 @@ class UnitTestsAppCoordinator: AppCoordinatorProtocol {
|
||||
init(appDelegate: AppDelegate) {
|
||||
windowManager = WindowManager(appDelegate: appDelegate)
|
||||
|
||||
AppSettings.configureWithSuiteName("io.element.elementx.unittests")
|
||||
AppSettings.resetAllSettings()
|
||||
|
||||
// As the tests take advantage of Rust's ability to redirect the log files, there is
|
||||
// often some debris left from the previous run, so we wipe the entire directory.
|
||||
// This is an NOT an advised way to delete logs in production, `Tracing.deleteLogFiles`
|
||||
|
||||
Reference in New Issue
Block a user