mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Initial implementation of AccountSettings. (#6275)
* Make the UserPreference macro also generate an accessor for the key name. * Initial implementation of AccountSettings. - Add an AccountUserDefaults storage with a userID prefix on the key. - Migrate the 2 values reset by AppSettings.resetSessionSpecificSettings to AccountSettings. * Rename UserSettings.volatile() to UserSettings.mock() Given it now has a userID parameter with a default value..
This commit is contained in:
@@ -467,14 +467,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
MXLog.info("The app was upgraded from \(oldVersion) to \(newVersion)")
|
||||
|
||||
if oldVersion < Version(1, 6, 0) {
|
||||
MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.")
|
||||
if !userSessionStore.userIDs.isEmpty {
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
appSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
}
|
||||
}
|
||||
|
||||
if oldVersion < Version(1, 6, 7) {
|
||||
Tracing.deleteLogFiles(in: Tracing.legacyLogsDirectory)
|
||||
MXLog.info("Migrating to v1.6.7, log files have been wiped")
|
||||
@@ -498,6 +490,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
await userSession.clientProxy.optimizeStores()
|
||||
MXLog.info("Finished optimizing client stores.")
|
||||
|
||||
if oldVersion < Version(1, 6, 0) {
|
||||
MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.")
|
||||
userSession.userSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
userSession.userSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
}
|
||||
|
||||
if oldVersion < Version(25, 6, 0) {
|
||||
MXLog.info("Migrating to version 25.06.0, migrating timeline media settings to account data.")
|
||||
performSettingsToAccountDataMigration(userSession: userSession)
|
||||
@@ -518,6 +516,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
appSettings.hasSignedInBefore = true
|
||||
}
|
||||
|
||||
if oldVersion < Version(26, 10, 1) {
|
||||
MXLog.info("Migrating to version 26.10.1, moving initial 'session specific' settings.")
|
||||
userSession.userSettings.migrateAppSettingsValueToAccountSettings(\.hasRunIdentityConfirmationOnboardingKey)
|
||||
userSession.userSettings.migrateAppSettingsValueToAccountSettings(\.searchBreadcrumbsKey)
|
||||
}
|
||||
|
||||
userSessionMigrationsOldVersion = nil
|
||||
}
|
||||
|
||||
@@ -863,7 +867,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
userSessionStore.logout(userSession: userSession)
|
||||
tearDownUserSession()
|
||||
|
||||
appSettings.resetSessionSpecificSettings()
|
||||
userSession.userSettings.resetSessionSpecificSettings()
|
||||
appHooks.remoteSettingsHook.reset(appSettings)
|
||||
|
||||
// Reset analytics
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// 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 Combine
|
||||
import Foundation
|
||||
import Macros
|
||||
|
||||
final nonisolated class AccountSettings: @unchecked Sendable {
|
||||
/// UserDefaults to be used on reads and writes.
|
||||
private let store: AccountUserDefaults
|
||||
private let userID: String
|
||||
|
||||
// MARK: Session
|
||||
|
||||
@UserPreference(defaultValue: false)
|
||||
var hasRunIdentityConfirmationOnboarding: Bool
|
||||
|
||||
// MARK: Search
|
||||
|
||||
/// The queries the user searched for and the rooms they opened from the results, most recent first.
|
||||
@UserPreference(defaultValue: [SearchBreadcrumb]())
|
||||
var searchBreadcrumbs: [SearchBreadcrumb]
|
||||
|
||||
init(userID: String, store: UserDefaultsProtocol) {
|
||||
self.store = .init(userID: userID, store: store)
|
||||
self.userID = userID
|
||||
}
|
||||
|
||||
func migrateAppSettingsValue(_ keyPath: KeyPath<AccountSettings, UserPreferenceKey>) {
|
||||
let storeKey = self[keyPath: keyPath].rawValue
|
||||
store.migrateAppSettingsValue(forKey: storeKey)
|
||||
}
|
||||
|
||||
func reset() {
|
||||
MXLog.warning("Resetting AccountSettings for \(userID).")
|
||||
store.reset()
|
||||
}
|
||||
}
|
||||
@@ -69,12 +69,6 @@ final nonisolated class AppSettings: @unchecked Sendable {
|
||||
store.reset()
|
||||
}
|
||||
|
||||
func resetSessionSpecificSettings() {
|
||||
MXLog.warning("Resetting the user session specific AppSettings.")
|
||||
resetHasRunIdentityConfirmationOnboarding()
|
||||
resetSearchBreadcrumbs()
|
||||
}
|
||||
|
||||
// MARK: - Hooks
|
||||
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
@@ -338,9 +332,6 @@ final nonisolated class AppSettings: @unchecked Sendable {
|
||||
@UserPreference(defaultValue: false)
|
||||
var hasRunNotificationPermissionsOnboarding: Bool
|
||||
|
||||
@UserPreference(defaultValue: false)
|
||||
var hasRunIdentityConfirmationOnboarding: Bool
|
||||
|
||||
@UserPreference(defaultValue: false)
|
||||
var hasRequestedLocationAlwaysLocationAuthorization: Bool
|
||||
|
||||
@@ -363,12 +354,6 @@ final nonisolated class AppSettings: @unchecked Sendable {
|
||||
@UserPreference(defaultValue: true)
|
||||
var showAllRoomListActivity: Bool
|
||||
|
||||
// MARK: - Search Screen
|
||||
|
||||
/// The queries the user searched for and the rooms they opened from the results, most recent first.
|
||||
@UserPreference(defaultValue: [SearchBreadcrumb]())
|
||||
var searchBreadcrumbs: [SearchBreadcrumb]
|
||||
|
||||
// MARK: - Room Screen
|
||||
|
||||
@UserPreference(defaultValue: AppBuildType.current == .debug)
|
||||
@@ -482,6 +467,10 @@ final nonisolated class AppSettings: @unchecked Sendable {
|
||||
self.store = store
|
||||
}
|
||||
|
||||
func userSettings(for userID: String) -> UserSettings {
|
||||
UserSettings(appSettings: self, accountSettings: .init(userID: userID, store: store))
|
||||
}
|
||||
|
||||
static func volatile() -> AppSettings {
|
||||
AppSettings(store: VolatileUserDefaults())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
/// A store that scopes all of its values to a single account.
|
||||
///
|
||||
/// Each value keeps its own key in the parent store, prefixed with the user ID so that writes
|
||||
/// remain atomic across the app and its extensions.
|
||||
final nonisolated class AccountUserDefaults: UserDefaultsProtocol, @unchecked Sendable {
|
||||
private let keyPrefix: String
|
||||
private let store: UserDefaultsProtocol
|
||||
|
||||
init(userID: String, store: UserDefaultsProtocol) {
|
||||
keyPrefix = "account[\(userID)]."
|
||||
self.store = store
|
||||
}
|
||||
|
||||
// MARK: Storage
|
||||
|
||||
func data(forKey key: String) -> Data? {
|
||||
store.data(forKey: keyPrefix + key)
|
||||
}
|
||||
|
||||
func object(forKey key: String) -> Any? {
|
||||
store.object(forKey: keyPrefix + key)
|
||||
}
|
||||
|
||||
func removeObject(forKey key: String) {
|
||||
store.removeObject(forKey: keyPrefix + key)
|
||||
}
|
||||
|
||||
func set(_ value: Any?, forKey key: String) {
|
||||
store.set(value, forKey: keyPrefix + key)
|
||||
}
|
||||
|
||||
// MARK: - Management
|
||||
|
||||
func migrateAppSettingsValue(forKey key: String) {
|
||||
guard let value = store.object(forKey: key) else {
|
||||
MXLog.info("Ignoring \(key), not set.")
|
||||
return
|
||||
}
|
||||
|
||||
store.set(value, forKey: keyPrefix + key)
|
||||
store.removeObject(forKey: key)
|
||||
}
|
||||
|
||||
func reset() {
|
||||
for key in dictionaryRepresentation().keys {
|
||||
removeObject(forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
func dictionaryRepresentation() -> [String: Any] {
|
||||
var representation = [String: Any]()
|
||||
for (key, value) in store.dictionaryRepresentation() where key.hasPrefix(keyPrefix) {
|
||||
representation[String(key.dropFirst(keyPrefix.count))] = value
|
||||
}
|
||||
return representation
|
||||
}
|
||||
}
|
||||
+1
@@ -15,6 +15,7 @@ nonisolated protocol UserDefaultsProtocol: AnyObject {
|
||||
func set(_ value: Any?, forKey key: String)
|
||||
|
||||
func reset()
|
||||
func dictionaryRepresentation() -> [String: Any]
|
||||
}
|
||||
|
||||
// MARK: - Codable handling
|
||||
+4
@@ -42,4 +42,8 @@ final nonisolated class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
|
||||
func reset() {
|
||||
storage = [:]
|
||||
}
|
||||
|
||||
func dictionaryRepresentation() -> [String: Any] {
|
||||
storage
|
||||
}
|
||||
}
|
||||
@@ -6,22 +6,23 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Macros
|
||||
|
||||
/// The settings for a signed in account, composed of the app wide settings and the settings
|
||||
/// specific to that account.
|
||||
@dynamicMemberLookup
|
||||
final nonisolated class UserSettings: Sendable {
|
||||
// TODO: @pixlwave Make this private after handling Advanced/Labs/Developer screen models.
|
||||
let app: AppSettings
|
||||
let account: AccountSettings
|
||||
private let account: AccountSettings
|
||||
|
||||
init(appSettings: AppSettings, accountSettings: AccountSettings) {
|
||||
self.app = appSettings
|
||||
self.account = accountSettings
|
||||
}
|
||||
|
||||
static func volatile() -> UserSettings {
|
||||
let appSettings = AppSettings.volatile()
|
||||
return UserSettings(appSettings: appSettings, accountSettings: .init())
|
||||
static func mock(userID: String = "@me:matrix.org") -> UserSettings {
|
||||
AppSettings.volatile().userSettings(for: userID)
|
||||
}
|
||||
|
||||
subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<AppSettings, Value>) -> Value {
|
||||
@@ -41,9 +42,12 @@ final nonisolated class UserSettings: Sendable {
|
||||
subscript<Value>(dynamicMember keyPath: KeyPath<AccountSettings, Value>) -> Value {
|
||||
account[keyPath: keyPath]
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings specific to an account.
|
||||
struct AccountSettings {
|
||||
// Placeholder for now, implementation to follow with a dedicated user defaults store scoped to a specific user ID.
|
||||
|
||||
func migrateAppSettingsValueToAccountSettings(_ keyPath: KeyPath<AccountSettings, UserPreferenceKey>) {
|
||||
account.migrateAppSettingsValue(keyPath)
|
||||
}
|
||||
|
||||
func resetSessionSpecificSettings() {
|
||||
account.reset()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import Foundation
|
||||
|
||||
struct UserSessionMockConfiguration {
|
||||
var clientProxy: ClientProxyProtocol = ClientProxyMock(.init())
|
||||
var userSettings: UserSettings = .volatile()
|
||||
var userSettings: UserSettings = .mock()
|
||||
var contentScannerService: ContentScannerServiceProtocol?
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ private struct VisualListItemLabelStyle: LabelStyle {
|
||||
// MARK: - Previews
|
||||
|
||||
struct VisualListItem_Previews: PreviewProvider, TestablePreview {
|
||||
static let strings = AnalyticsPromptScreenStrings(termsURL: UserSettings.volatile().analyticsTermsURL)
|
||||
static let strings = AnalyticsPromptScreenStrings(termsURL: UserSettings.mock().analyticsTermsURL)
|
||||
|
||||
static var testImage1: some View {
|
||||
Image(systemName: "circle")
|
||||
|
||||
@@ -405,7 +405,7 @@ struct CallScreen_Previews: PreviewProvider {
|
||||
voiceOnly: false,
|
||||
colorScheme: .light),
|
||||
allowPictureInPicture: false,
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
isSpace: Bool = false,
|
||||
selectionMode: CreateRoomScreenSpaceSelectionMode = .editableSpacesList(preSelectedSpace: nil),
|
||||
isAliasAvailable: Bool = true) -> CreateRoomScreenViewModel {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.knockingEnabled = isKnockingEnabled
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(userIDServerName: "example.org",
|
||||
|
||||
@@ -65,7 +65,7 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
return CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil),
|
||||
|
||||
@@ -103,7 +103,7 @@ struct EmojiPickerScreen: View {
|
||||
@available(iOS 26.0, *)
|
||||
struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
continuation: AsyncStream<String>.makeStream().continuation)
|
||||
|
||||
static var previews: some View {
|
||||
@@ -115,7 +115,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
struct EmojiPickerScreenSheet_Previews: PreviewProvider {
|
||||
static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
continuation: AsyncStream<String>.makeStream().continuation)
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
+2
-2
@@ -61,10 +61,10 @@ struct RoomListFiltersEmptyStateView_Previews: PreviewProvider, TestablePreview
|
||||
VStack(spacing: 24) {
|
||||
ForEach(RoomListFilter.allCases) { filter in
|
||||
RoomListFiltersEmptyStateView(state: .init(activeFilters: [filter],
|
||||
userSettings: .volatile()))
|
||||
userSettings: .mock()))
|
||||
}
|
||||
RoomListFiltersEmptyStateView(state: .init(activeFilters: [.people, .favourites],
|
||||
userSettings: .volatile()))
|
||||
userSettings: .mock()))
|
||||
}
|
||||
.padding(.bottom)
|
||||
.previewLayout(.sizeThatFits)
|
||||
|
||||
@@ -92,10 +92,10 @@ struct RoomListFiltersView: View {
|
||||
|
||||
struct RoomListFiltersView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
RoomListFiltersView(state: .constant(.init(userSettings: .volatile())))
|
||||
RoomListFiltersView(state: .constant(.init(userSettings: .mock())))
|
||||
RoomListFiltersView(state: .constant(.init(activeFilters: [.rooms, .favourites],
|
||||
userSettings: .volatile())))
|
||||
userSettings: .mock())))
|
||||
RoomListFiltersView(state: .constant(.init(activeFilters: [.lowPriority],
|
||||
userSettings: .volatile())))
|
||||
userSettings: .mock())))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
bugReportService: BugReportServiceMock(.init()),
|
||||
notificationManager: NotificationManagerMock(),
|
||||
|
||||
@@ -145,7 +145,7 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
|
||||
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([])))))))
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
bugReportService: BugReportServiceMock(.init()),
|
||||
notificationManager: NotificationManagerMock(),
|
||||
|
||||
@@ -201,7 +201,7 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
bugReportService: BugReportServiceMock(.init()),
|
||||
notificationManager: NotificationManagerMock(),
|
||||
|
||||
@@ -133,7 +133,7 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
bugReportService: BugReportServiceMock(.init()),
|
||||
notificationManager: NotificationManagerMock(),
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
bugReportService: BugReportServiceMock(.init()),
|
||||
notificationManager: NotificationManagerMock(),
|
||||
|
||||
@@ -402,7 +402,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
|
||||
self.isSpace = isSpace
|
||||
self.customPreviewName = customPreviewName
|
||||
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars))
|
||||
clientProxy.canJoinRoomWithReturnValue = canJoinRoom
|
||||
|
||||
@@ -432,7 +432,7 @@ extension LocationSharingScreenViewModel {
|
||||
let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID))
|
||||
roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock
|
||||
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
return LocationSharingScreenViewModel(interactionMode: interactionMode,
|
||||
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
|
||||
|
||||
+1
-1
@@ -314,7 +314,7 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
}
|
||||
|
||||
+1
-1
@@ -393,7 +393,7 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview {
|
||||
title: "App Icon.png",
|
||||
shouldShowCaptionWarning: true,
|
||||
galleryEnabled: true,
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
|
||||
+1
-1
@@ -102,6 +102,6 @@ struct AnalyticsPromptScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
static func makeViewModel(showTerms: Bool = true) -> AnalyticsPromptScreenViewModel {
|
||||
AnalyticsPromptScreenViewModel(termsURL: showTerms ? UserSettings.volatile().analyticsTermsURL : nil)
|
||||
AnalyticsPromptScreenViewModel(termsURL: showTerms ? UserSettings.mock().analyticsTermsURL : nil)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userSession.sessionSecurityStatePublisher = CurrentValuePublisher<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: recoveryState))
|
||||
|
||||
return IdentityConfirmationScreenViewModel(userSession: userSession,
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -289,7 +289,7 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview {
|
||||
flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View {
|
||||
let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(),
|
||||
flow: flow,
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
verificationState: state)
|
||||
|
||||
|
||||
+3
-3
@@ -83,7 +83,7 @@ struct PinnedEventsTimelineScreen: View {
|
||||
struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()))
|
||||
|
||||
static let emptyTimelineViewModel = makeTimelineViewModel(timelineItems: [])
|
||||
@@ -106,7 +106,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let eventIDs = timelineItems.compactMap { ($0 as? EventBasedTimelineItemProtocol)?.id.eventID }
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: .pinned, timelineItems: timelineItems))
|
||||
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.messageMultiSelectEnabled = isSelecting
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
@@ -117,7 +117,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return RoomDetailsEditScreenViewModel(roomProxy: roomProxy,
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()),
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return .init(roomProxy: roomProxy,
|
||||
userSession: UserSessionMock(.init()),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
@@ -474,7 +474,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return .init(roomProxy: roomProxy,
|
||||
userSession: UserSessionMock(.init()),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
@@ -513,7 +513,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
return .init(roomProxy: roomProxy,
|
||||
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -852,7 +852,7 @@ extension ComposerToolbarViewModel {
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
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 userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
return ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
|
||||
wysiwygViewModel: WysiwygComposerViewModel(),
|
||||
|
||||
@@ -395,7 +395,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
||||
powerLevelsConfiguration: .init(canUserSendMessage: canSendMessage)))
|
||||
let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
|
||||
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.messageMultiSelectEnabled = isSelecting
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
|
||||
@@ -629,31 +629,31 @@ struct SearchScreen_Previews: PreviewProvider, TestablePreview {
|
||||
clientProxy: makeClientProxy(),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: UserSettings.volatile())
|
||||
userSettings: UserSettings.mock())
|
||||
static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||
clientProxy: makeClientProxy(),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
initialSearchQuery: "John Doe")
|
||||
static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
|
||||
clientProxy: makeClientProxy(),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
initialSearchQuery: "Foundation")
|
||||
static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||
clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
initialSearchQuery: "Foundation",
|
||||
initialSearchMode: .messages)
|
||||
static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||
clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
initialSearchQuery: "Foundation",
|
||||
initialSearchMode: .messages)
|
||||
|
||||
@@ -708,7 +708,7 @@ struct SearchScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
private static func makeUserSettings(breadcrumbs: [SearchBreadcrumb]) -> UserSettings {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.searchBreadcrumbs = breadcrumbs
|
||||
return userSettings
|
||||
}
|
||||
|
||||
+9
-9
@@ -235,7 +235,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
joinRule: .invite)),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
appHooks: AppHooks())
|
||||
|
||||
static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
@@ -245,7 +245,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
appHooks: AppHooks())
|
||||
|
||||
static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
@@ -253,11 +253,11 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
joinRule: .public)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
appHooks: AppHooks())
|
||||
|
||||
static let singleSpaceMembersViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
let space = [SpaceServiceRoom].mockSingleRoom[0]
|
||||
|
||||
@@ -274,7 +274,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let multipleSpacesMembersViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
let spaces = [SpaceServiceRoom].mockJoinedSpaces
|
||||
|
||||
@@ -291,7 +291,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let askToJoinViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.knockingEnabled = true
|
||||
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
@@ -306,7 +306,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let singleAskToJoinSpaceMembersViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.knockingEnabled = true
|
||||
|
||||
let space = [SpaceServiceRoom].mockSingleRoom[0]
|
||||
@@ -324,7 +324,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let multipleAskToJoinSpacesMembersViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.knockingEnabled = true
|
||||
|
||||
let spaces = [SpaceServiceRoom].mockJoinedSpaces
|
||||
@@ -349,7 +349,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
appHooks: AppHooks())
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ struct AnalyticsSettingsScreen: View {
|
||||
|
||||
struct AnalyticsSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
let viewModel = AnalyticsSettingsScreenViewModel(userSettings: userSettings,
|
||||
analytics: AnalyticsServiceMock(.init()))
|
||||
AnalyticsSettingsScreen(context: viewModel.context)
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ struct LegalInformationScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct LegalInformationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = LegalInformationScreenViewModel(userSettings: .volatile())
|
||||
static let viewModel = LegalInformationScreenViewModel(userSettings: .mock())
|
||||
static var previews: some View {
|
||||
LegalInformationScreen(context: viewModel.context)
|
||||
}
|
||||
|
||||
+2
-2
@@ -262,7 +262,7 @@ struct NotificationSettingsScreen: View {
|
||||
@available(iOS 26.0, *)
|
||||
struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel: NotificationSettingsScreenViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
let notificationCenter = UserNotificationCenterMock()
|
||||
notificationCenter.authorizationStatusReturnValue = .notDetermined
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
@@ -290,7 +290,7 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}()
|
||||
|
||||
static let viewModelConfigurationMismatch: NotificationSettingsScreenViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
let notificationCenter = UserNotificationCenterMock()
|
||||
notificationCenter.authorizationStatusReturnValue = .notDetermined
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
|
||||
@@ -321,7 +321,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
deviceID: "AAAAAAAAAAA",
|
||||
displayName: "Alice Liddell",
|
||||
status: .mockFocussing))))
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.multiAccountEnabled = true
|
||||
return SettingsScreenViewModel(userSession: userSession,
|
||||
userSettings: userSettings,
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ struct UserDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||
canChangeDisplayName: canChangeProfile))))
|
||||
|
||||
return UserDetailsEditScreenViewModel(userSession: userSession,
|
||||
mediaUploadingPreprocessor: .init(userSettings: .volatile()),
|
||||
mediaUploadingPreprocessor: .init(userSettings: .mock()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
canonicalAlias: "#space:matrix.org",
|
||||
members: members)),
|
||||
userSession: UserSessionMock(.init()),
|
||||
userSettings: UserSettings.volatile(),
|
||||
userSettings: UserSettings.mock(),
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -154,7 +154,7 @@ struct StartChatScreen: View {
|
||||
|
||||
struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
let userDiscoveryService = UserDiscoveryServiceMock()
|
||||
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
|
||||
|
||||
@@ -1306,7 +1306,7 @@ extension TimelineViewModel {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
|
||||
isViewSourceEnabled: true,
|
||||
areThreadsEnabled: true,
|
||||
timelineKind: .live,
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()))
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()))
|
||||
guard let actions = provider.makeActions() else { return nil }
|
||||
|
||||
if var textItem = item as? TextRoomTimelineItem {
|
||||
|
||||
@@ -52,7 +52,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
}()
|
||||
|
||||
@@ -426,7 +426,7 @@ private extension TimelineItemKeyForwarder {
|
||||
|
||||
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel: TimelineViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.threadsEnabled = true
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
@@ -445,7 +445,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
||||
}()
|
||||
|
||||
static let viewModelWithPins: TimelineViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.threadsEnabled = true
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
@@ -466,7 +466,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
||||
static let unsafeViewModel = TimelineViewModel.mock(contentScannerService: ContentScannerServiceMock(.init(scanResult: false)))
|
||||
|
||||
static let selectingViewModel: TimelineViewModel = {
|
||||
let userSettings = UserSettings.volatile()
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.messageMultiSelectEnabled = true
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appMediator: AppMediatorMock(.init()),
|
||||
analyticsService: AnalyticsServiceMock(.init()),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
|
||||
|
||||
|
||||
@@ -232,11 +232,10 @@ class AuthenticationService: AuthenticationServiceProtocol {
|
||||
let qrCodeHandler = client.newLoginWithQrCodeHandler(oauthConfiguration: appSettings.oAuthConfiguration.rustValue)
|
||||
try await qrCodeHandler.scan(qrCodeData: qrData, progressListener: listener)
|
||||
|
||||
// Since the QR code login flow includes verification.
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
|
||||
switch await userSession(for: client) {
|
||||
case .success(let userSession):
|
||||
// Since the QR code login flow includes verification.
|
||||
userSession.userSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
progressSubject.send(.signedIn(userSession))
|
||||
case .failure(let error):
|
||||
progressSubject.send(completion: .failure(error))
|
||||
@@ -367,7 +366,7 @@ class AuthenticationService: AuthenticationServiceProtocol {
|
||||
MXLog.info("Classic app account secrets imported.")
|
||||
|
||||
// Importing the secrets automatically verifies the session.
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
appSettings.userSettings(for: classicAppAccount.userID).hasRunIdentityConfirmationOnboarding = true
|
||||
} catch {
|
||||
MXLog.error("Failed to import secrets for Classic app account: \(error)")
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
return .failure(.missingCredentials)
|
||||
}
|
||||
|
||||
let userSettings = UserSettings(appSettings: appSettings, accountSettings: .init())
|
||||
let userSettings = appSettings.userSettings(for: credentials.userID)
|
||||
|
||||
switch await restorePreviousLogin(credentials, userSettings: userSettings) {
|
||||
case .success(let clientProxy):
|
||||
@@ -83,7 +83,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
do {
|
||||
let session = try client.session()
|
||||
let userID = try client.userId()
|
||||
let userSettings = UserSettings(appSettings: appSettings, accountSettings: .init())
|
||||
let userSettings = appSettings.userSettings(for: userID)
|
||||
let clientProxy = try await setupProxyForClient(client, userSettings: userSettings)
|
||||
|
||||
keychainController.setRestorationToken(RestorationToken(session: session,
|
||||
|
||||
@@ -298,7 +298,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -318,7 +318,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -338,7 +338,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -357,7 +357,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -382,7 +382,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -407,7 +407,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -431,7 +431,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -457,7 +457,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -482,7 +482,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -503,7 +503,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -537,7 +537,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -558,7 +558,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -579,7 +579,7 @@ class MockScreen: Identifiable {
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(userSettings: .volatile()),
|
||||
emojiProvider: EmojiProvider(userSettings: .mock()),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
@@ -597,14 +597,15 @@ class MockScreen: Identifiable {
|
||||
requestDelay: .seconds(5))
|
||||
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy,
|
||||
flow: .deviceInitiator,
|
||||
userSettings: .volatile(),
|
||||
userSettings: .mock(),
|
||||
mediaProvider: MediaProviderMock(.init()))
|
||||
return SessionVerificationScreenCoordinator(parameters: parameters)
|
||||
case .userSessionScreen, .userSessionScreenReply, .userSessionSpacesFlow:
|
||||
let appSettings: AppSettings = appSettings
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
appSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
appSettings.analyticsConsentState = .optedOut
|
||||
let userID = "@mock:client.com"
|
||||
let userSettings = appSettings.userSettings(for: userID)
|
||||
userSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
userSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
userSettings.analyticsConsentState = .optedOut
|
||||
|
||||
let roomSummaries: [RoomSummary] = if id == .userSessionSpacesFlow {
|
||||
[[RoomSummary].mockSpaceInvites[0]] + .mockRooms
|
||||
@@ -612,7 +613,7 @@ class MockScreen: Identifiable {
|
||||
.mockRooms
|
||||
}
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com",
|
||||
let clientProxy = ClientProxyMock(.init(userID: userID,
|
||||
deviceID: "MOCKCLIENT",
|
||||
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))),
|
||||
spaceServiceConfiguration: .init(topLevelSpaces: .mockSpaceList.filter(\.isSpace) + .mockSingleRoom),
|
||||
@@ -634,8 +635,7 @@ class MockScreen: Identifiable {
|
||||
|
||||
let timelineControllerFactory = TimelineControllerFactoryMock(.init(timelineController: timelineController))
|
||||
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy,
|
||||
userSettings: UserSettings(appSettings: appSettings, accountSettings: .init())))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
|
||||
let flowCoordinator = UserSessionFlowCoordinator(isNewLogin: false,
|
||||
navigationRootCoordinator: navigationRootCoordinator,
|
||||
appLockService: AppLockService(keychainController: KeychainControllerMock(),
|
||||
@@ -826,14 +826,15 @@ class MockScreen: Identifiable {
|
||||
navigationRootCoordinator.setSheetCoordinator(navigationStackCoordinator)
|
||||
return PlaceholderScreenCoordinator(hideBrandChrome: false)
|
||||
case .autoUpdatingTimeline:
|
||||
let userSettings = UserSettings(appSettings: appSettings, accountSettings: .init())
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
appSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
appSettings.analyticsConsentState = .optedOut
|
||||
let userID = "@mock:client.com"
|
||||
let userSettings = appSettings.userSettings(for: userID)
|
||||
userSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
userSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
userSettings.analyticsConsentState = .optedOut
|
||||
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: false))
|
||||
navigationRootCoordinator.setRootCoordinator(navigationSplitCoordinator)
|
||||
|
||||
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
||||
let clientProxy = ClientProxyMock(.init(userID: userID, roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
|
||||
|
||||
let roomProxy = JoinedRoomProxyMock(.init(id: "whatever", name: "okay", shouldUseAutoUpdatingTimeline: true))
|
||||
@@ -905,6 +906,6 @@ class MockScreen: Identifiable {
|
||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")),
|
||||
mediaProvider: MediaProviderMock(.init()),
|
||||
userSettings: .volatile())
|
||||
userSettings: .mock())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user