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:
Doug
2026-10-06 17:52:24 +01:00
committed by GitHub
parent acd18f3aa9
commit 93825c01ad
96 changed files with 623 additions and 248 deletions
@@ -16,7 +16,7 @@
/// persisted under a legacy key). /// persisted under a legacy key).
/// ///
/// A `reset<Name>()` method is also generated, which clears the stored value so it reverts to the /// A `reset<Name>()` method is also generated, which clears the stored value so it reverts to the
/// default. /// default. Non-volatile preferences also get a `<name>Key` property exposing the storage key.
@attached(accessor) @attached(accessor)
@attached(peer, names: arbitrary) @attached(peer, names: arbitrary)
public macro UserPreference<Value>(key: String? = nil, defaultValue: Value, volatile: Bool = false) = public macro UserPreference<Value>(key: String? = nil, defaultValue: Value, volatile: Bool = false) =
@@ -27,3 +27,13 @@ public macro UserPreference<Value>(key: String? = nil, defaultValue: Value, vola
@attached(peer, names: arbitrary) @attached(peer, names: arbitrary)
public macro UserPreference(key: String? = nil, volatile: Bool = false) = public macro UserPreference(key: String? = nil, volatile: Bool = false) =
#externalMacro(module: "MacrosImplementation", type: "UserPreferenceMacro") #externalMacro(module: "MacrosImplementation", type: "UserPreferenceMacro")
/// The storage key of a `@UserPreference`, distinct from `String` so that only a generated
/// `<name>Key` property can be passed where a preference key is expected.
public struct UserPreferenceKey: Sendable {
public let rawValue: String
public init(_ rawValue: String) {
self.rawValue = rawValue
}
}
@@ -45,6 +45,10 @@ enum UserPreferenceMacro {
"_\(raw: name)VolatileValue" "_\(raw: name)VolatileValue"
} }
var keyPropertyName: TokenSyntax {
"\(raw: name)Key"
}
var resetMethodName: TokenSyntax { var resetMethodName: TokenSyntax {
"reset\(raw: name.prefix(1).uppercased() + name.dropFirst())" "reset\(raw: name.prefix(1).uppercased() + name.dropFirst())"
} }
@@ -157,6 +161,14 @@ extension UserPreferenceMacro: PeerMacro {
} }
""") """)
if !preference.isVolatile {
peers.append("""
var \(preference.keyPropertyName): UserPreferenceKey {
.init(\(preference.key))
}
""")
}
peers.append(resetMethod(for: preference)) peers.append(resetMethod(for: preference))
return peers return peers
@@ -5,7 +5,7 @@
// Please see LICENSE files in the repository root for full details. // Please see LICENSE files in the repository root for full details.
// //
import MacrosImplementation @testable import MacrosImplementation
import SwiftSyntaxMacrosTestSupport import SwiftSyntaxMacrosTestSupport
import XCTest import XCTest
@@ -35,6 +35,10 @@ final class UserPreferenceMacroTests: XCTestCase {
_hasSeenNewSoundBannerSubject.prepend(hasSeenNewSoundBanner).eraseToAnyPublisher() _hasSeenNewSoundBannerSubject.prepend(hasSeenNewSoundBanner).eraseToAnyPublisher()
} }
var hasSeenNewSoundBannerKey: UserPreferenceKey {
.init("hasSeenNewSoundBanner")
}
func resetHasSeenNewSoundBanner() { func resetHasSeenNewSoundBanner() {
store.removeObject(forKey: "hasSeenNewSoundBanner") store.removeObject(forKey: "hasSeenNewSoundBanner")
} }
@@ -65,6 +69,10 @@ final class UserPreferenceMacroTests: XCTestCase {
_liveLocationSharingSessionsByRoomIDSubject.prepend(liveLocationSharingSessionsByRoomID).eraseToAnyPublisher() _liveLocationSharingSessionsByRoomIDSubject.prepend(liveLocationSharingSessionsByRoomID).eraseToAnyPublisher()
} }
var liveLocationSharingSessionsByRoomIDKey: UserPreferenceKey {
.init("liveLocationSharingTimeoutDatesByRoomID")
}
func resetLiveLocationSharingSessionsByRoomID() { func resetLiveLocationSharingSessionsByRoomID() {
store.removeObject(forKey: "liveLocationSharingTimeoutDatesByRoomID") store.removeObject(forKey: "liveLocationSharingTimeoutDatesByRoomID")
} }
@@ -95,6 +103,10 @@ final class UserPreferenceMacroTests: XCTestCase {
_pusherProfileTagSubject.prepend(pusherProfileTag).eraseToAnyPublisher() _pusherProfileTagSubject.prepend(pusherProfileTag).eraseToAnyPublisher()
} }
var pusherProfileTagKey: UserPreferenceKey {
.init("pusherProfileTag")
}
func resetPusherProfileTag() { func resetPusherProfileTag() {
store.removeObject(forKey: "pusherProfileTag") store.removeObject(forKey: "pusherProfileTag")
} }
@@ -125,6 +137,10 @@ final class UserPreferenceMacroTests: XCTestCase {
_viewSourceEnabledSubject.prepend(viewSourceEnabled).eraseToAnyPublisher() _viewSourceEnabledSubject.prepend(viewSourceEnabled).eraseToAnyPublisher()
} }
var viewSourceEnabledKey: UserPreferenceKey {
.init("viewSourceEnabled")
}
func resetViewSourceEnabled() { func resetViewSourceEnabled() {
store.removeObject(forKey: "viewSourceEnabled") store.removeObject(forKey: "viewSourceEnabled")
} }
+58 -26
View File
@@ -87,6 +87,7 @@
0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */; }; 0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */; };
0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; }; 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; };
0B05A35FF5D1ED9E8A0B41A7 /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */; }; 0B05A35FF5D1ED9E8A0B41A7 /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */; };
0B30DC7D9D445C405ADCB5FA /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3994D186AC9893BEE458ECF /* VolatileUserDefaults.swift */; };
0B9436A91CFA658202400465 /* WaitingConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E21DC54FCC2A7F78532923F /* WaitingConfirmation.swift */; }; 0B9436A91CFA658202400465 /* WaitingConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E21DC54FCC2A7F78532923F /* WaitingConfirmation.swift */; };
0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */; }; 0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */; };
0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */; }; 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */; };
@@ -113,6 +114,7 @@
0F81DEE3E02A6549B20DF09A /* DeactivateAccountScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633924B26ACCD29C18BEF4E8 /* DeactivateAccountScreenViewModelProtocol.swift */; }; 0F81DEE3E02A6549B20DF09A /* DeactivateAccountScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633924B26ACCD29C18BEF4E8 /* DeactivateAccountScreenViewModelProtocol.swift */; };
0FA03F5A33C0857231B32B44 /* ReportRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDB0B87D925AE830E32621 /* ReportRoomScreenViewModel.swift */; }; 0FA03F5A33C0857231B32B44 /* ReportRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDB0B87D925AE830E32621 /* ReportRoomScreenViewModel.swift */; };
101C8BFCAE35F43F37A6D8ED /* NotificationToneManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18678D0A4177D8F0A255BC36 /* NotificationToneManagerMock.swift */; }; 101C8BFCAE35F43F37A6D8ED /* NotificationToneManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18678D0A4177D8F0A255BC36 /* NotificationToneManagerMock.swift */; };
106E3126B0C49231381B5B80 /* AccountUserDefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96792E7EE6742172DA3A35E /* AccountUserDefaultsTests.swift */; };
108D3C0707A90B0F848CDBB9 /* ResolveVerifiedUserSendFailureScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60011EF0086E49DBD78E16E5 /* ResolveVerifiedUserSendFailureScreenModels.swift */; }; 108D3C0707A90B0F848CDBB9 /* ResolveVerifiedUserSendFailureScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60011EF0086E49DBD78E16E5 /* ResolveVerifiedUserSendFailureScreenModels.swift */; };
109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */; }; 109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */; };
10D60D287025B71F4743A425 /* RoomDirectorySearchProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */; }; 10D60D287025B71F4743A425 /* RoomDirectorySearchProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */; };
@@ -183,7 +185,6 @@
1AE4532D92E6ED42BFE87064 /* JoinRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A566F8F2C27B99E1FB80C69B /* JoinRule.swift */; }; 1AE4532D92E6ED42BFE87064 /* JoinRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A566F8F2C27B99E1FB80C69B /* JoinRule.swift */; };
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; }; 1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
1AF4A82B4332CAD2DB3EB5DA /* TopBannerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78483F0143E185EDC6ECD741 /* TopBannerModifier.swift */; }; 1AF4A82B4332CAD2DB3EB5DA /* TopBannerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78483F0143E185EDC6ECD741 /* TopBannerModifier.swift */; };
1B1404DD4BB2C5079B074210 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA4547BE58E17899E95CDE /* UserDefaultsProtocol.swift */; };
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; }; 1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; };
1B2F9F368619FFF8C63C87CC /* BugReportScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */; }; 1B2F9F368619FFF8C63C87CC /* BugReportScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */; };
1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */; }; 1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */; };
@@ -261,13 +262,11 @@
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; }; 2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; };
28426806399E3659BEBC5918 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6ED50FE104992419310EEB /* NotificationHandler.swift */; }; 28426806399E3659BEBC5918 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6ED50FE104992419310EEB /* NotificationHandler.swift */; };
288408E6151D7BD3EBAA073A /* RoomScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B343C5255FB408DDE853CFDF /* RoomScreenHook.swift */; }; 288408E6151D7BD3EBAA073A /* RoomScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B343C5255FB408DDE853CFDF /* RoomScreenHook.swift */; };
28A494A66D0F21EC1EC4EB11 /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2F56C9FFE8D55375CED9741 /* VolatileUserDefaults.swift */; };
28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */; }; 28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */; };
291A3E0EECD496D0FCC2ADAA /* TimelineScrollButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E14E3688FF3532456A656 /* TimelineScrollButton.swift */; }; 291A3E0EECD496D0FCC2ADAA /* TimelineScrollButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E14E3688FF3532456A656 /* TimelineScrollButton.swift */; };
29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; }; 29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; };
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; }; 2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */; }; 298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */; };
29E411E37D3FBF3899B3ED69 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA4547BE58E17899E95CDE /* UserDefaultsProtocol.swift */; };
29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; 29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
2A4B7856611589DD7B1B36CA /* SearchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79A78330B9329E3A99E4105 /* SearchScreen.swift */; }; 2A4B7856611589DD7B1B36CA /* SearchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79A78330B9329E3A99E4105 /* SearchScreen.swift */; };
2A4F8B76E1F99DE95D5867E6 /* ClassicAppManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BAD3D9BB44B2AED7CBB93 /* ClassicAppManagerMock.swift */; }; 2A4F8B76E1F99DE95D5867E6 /* ClassicAppManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BAD3D9BB44B2AED7CBB93 /* ClassicAppManagerMock.swift */; };
@@ -466,6 +465,7 @@
4A361E8BAFFA20B9719B47F5 /* InviteUsersConfirmationSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E97CF050B0168F3D605F0E9 /* InviteUsersConfirmationSheetView.swift */; }; 4A361E8BAFFA20B9719B47F5 /* InviteUsersConfirmationSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E97CF050B0168F3D605F0E9 /* InviteUsersConfirmationSheetView.swift */; };
4A4110369DBB79E4A314F415 /* ComposerToolbarViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */; }; 4A4110369DBB79E4A314F415 /* ComposerToolbarViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */; };
4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; }; 4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; };
4A7957D034F5D96909127881 /* AccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C071F3013E8C6DAC7FB768 /* AccountSettings.swift */; };
4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */; }; 4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */; };
4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; }; 4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; };
4A9786829B79BD13EF1626C1 /* NativeCallSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2316BADD6C1119C1FA229 /* NativeCallSystem.swift */; }; 4A9786829B79BD13EF1626C1 /* NativeCallSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2316BADD6C1119C1FA229 /* NativeCallSystem.swift */; };
@@ -522,6 +522,7 @@
513AF15E0E84711B80D04B1B /* ReportRoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3E9684DCE6B66BD0B5DF67 /* ReportRoomScreenViewModelTests.swift */; }; 513AF15E0E84711B80D04B1B /* ReportRoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3E9684DCE6B66BD0B5DF67 /* ReportRoomScreenViewModelTests.swift */; };
51A075328D68FB4AE65C43B5 /* SearchServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD6FFE581238BD30B53BA0A /* SearchServiceProxy.swift */; }; 51A075328D68FB4AE65C43B5 /* SearchServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD6FFE581238BD30B53BA0A /* SearchServiceProxy.swift */; };
51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; }; 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; };
51DBB7D725080FDAA4AB1412 /* UserSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE997F400545F3265935B53 /* UserSettingsTests.swift */; };
522269133E6F65F68482F4F4 /* RemotePreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */; }; 522269133E6F65F68482F4F4 /* RemotePreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */; };
52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
52511848C094F3097F858F00 /* AvatarSettingsButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D3DA6F684A8FD5A70644CDA /* AvatarSettingsButtonLabel.swift */; }; 52511848C094F3097F858F00 /* AvatarSettingsButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D3DA6F684A8FD5A70644CDA /* AvatarSettingsButtonLabel.swift */; };
@@ -687,7 +688,6 @@
6B8F03A85E83755D98DF0443 /* SearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C4724D5CB16CFA5853EF8F9 /* SearchScreenViewModel.swift */; }; 6B8F03A85E83755D98DF0443 /* SearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C4724D5CB16CFA5853EF8F9 /* SearchScreenViewModel.swift */; };
6BA9214F31A24C7A84287A56 /* SentryEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337AD37403015231CAE3E80B /* SentryEvent.swift */; }; 6BA9214F31A24C7A84287A56 /* SentryEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337AD37403015231CAE3E80B /* SentryEvent.swift */; };
6BAE34CFA9821709CFE61E50 /* DeveloperOptionsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F60FDB3AEFC60830BD289FE /* DeveloperOptionsScreenHook.swift */; }; 6BAE34CFA9821709CFE61E50 /* DeveloperOptionsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F60FDB3AEFC60830BD289FE /* DeveloperOptionsScreenHook.swift */; };
6BEB10499149444909EBE42F /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */; };
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; }; 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
6C8BAF1E91618D69E7D652B2 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; 6C8BAF1E91618D69E7D652B2 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; };
6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; }; 6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; };
@@ -714,6 +714,7 @@
706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; }; 706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; };
7070E5CA0095CBEFAA7DE466 /* MediaEventsTimelineScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F505E3D79018B6EFF953F647 /* MediaEventsTimelineScreenViewModelTests.swift */; }; 7070E5CA0095CBEFAA7DE466 /* MediaEventsTimelineScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F505E3D79018B6EFF953F647 /* MediaEventsTimelineScreenViewModelTests.swift */; };
707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */; }; 707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */; };
708B77D5E65BB48D44732236 /* AccountUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */; };
708FC3184CCED825F0A36273 /* RoomThreadListServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE06F4A71FD46C9D8CD432E /* RoomThreadListServiceProxy.swift */; }; 708FC3184CCED825F0A36273 /* RoomThreadListServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE06F4A71FD46C9D8CD432E /* RoomThreadListServiceProxy.swift */; };
709A9B52FC26B4CB86B8B020 /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */; }; 709A9B52FC26B4CB86B8B020 /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */; };
70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */; }; 70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */; };
@@ -768,6 +769,7 @@
77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */; }; 77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */; };
77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */; }; 77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */; };
7807B1DEE32617896886A8E5 /* FormattingToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */; }; 7807B1DEE32617896886A8E5 /* FormattingToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */; };
780C0394F8A10C4BCAC85DDC /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07204157037AB27CE47AA66C /* UserDefaultsProtocol.swift */; };
783FFA8F0DB76A1CB23B0ECE /* CLLocationCoordinate2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FC06B3414D3BBD709E72E4 /* CLLocationCoordinate2D.swift */; }; 783FFA8F0DB76A1CB23B0ECE /* CLLocationCoordinate2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FC06B3414D3BBD709E72E4 /* CLLocationCoordinate2D.swift */; };
784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; }; 784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; };
785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */; }; 785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */; };
@@ -866,6 +868,7 @@
874704A177B0A6D78E037908 /* MapLibreInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 842F63AA68E8EB410B1BA29F /* MapLibreInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 874704A177B0A6D78E037908 /* MapLibreInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 842F63AA68E8EB410B1BA29F /* MapLibreInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */; }; 877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */; };
878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; }; 878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; };
879013B1A7DA779C7E0C56A4 /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004397AC54CAE108B6E2385D /* TrackedUserDefaults.swift */; };
87E8C31FCF9276F15CB0B408 /* ThreadTimelineScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1C19A4BE46EDE1411ECCE /* ThreadTimelineScreenViewModelProtocol.swift */; }; 87E8C31FCF9276F15CB0B408 /* ThreadTimelineScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C1C19A4BE46EDE1411ECCE /* ThreadTimelineScreenViewModelProtocol.swift */; };
8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */; }; 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */; };
88272A714D81BC507F76A1EE /* RageshakeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */; }; 88272A714D81BC507F76A1EE /* RageshakeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */; };
@@ -907,7 +910,6 @@
8C706DA7EAC0974CA2F8F1CD /* MentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15748C254911E3654C93B0ED /* MentionBuilder.swift */; }; 8C706DA7EAC0974CA2F8F1CD /* MentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15748C254911E3654C93B0ED /* MentionBuilder.swift */; };
8C91D242BEEC657FABCC0B95 /* BlockedUsersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */; }; 8C91D242BEEC657FABCC0B95 /* BlockedUsersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */; };
8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */; }; 8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */; };
8CFB8BB99F25FA34B6C6BE86 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA4547BE58E17899E95CDE /* UserDefaultsProtocol.swift */; };
8CFDA5F1562479CB3A34D277 /* RedactedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */; }; 8CFDA5F1562479CB3A34D277 /* RedactedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */; };
8CFDC1309E8E5192EC2B04FE /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = D48D415C7A4284DEBEB34924 /* portrait_test_video.mp4 */; }; 8CFDC1309E8E5192EC2B04FE /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = D48D415C7A4284DEBEB34924 /* portrait_test_video.mp4 */; };
8D24671992A1C1753B211221 /* EncryptionResetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BB11A792EF6F70B95B467E /* EncryptionResetTests.swift */; }; 8D24671992A1C1753B211221 /* EncryptionResetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BB11A792EF6F70B95B467E /* EncryptionResetTests.swift */; };
@@ -929,6 +931,7 @@
90C683C87BF6D39419402E5B /* AuthenticationClassicAppBackupInstructionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B0E0A2F16603E7C827C295 /* AuthenticationClassicAppBackupInstructionsView.swift */; }; 90C683C87BF6D39419402E5B /* AuthenticationClassicAppBackupInstructionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B0E0A2F16603E7C827C295 /* AuthenticationClassicAppBackupInstructionsView.swift */; };
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
90F7C2C3DF76B3B00B58CB57 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07204157037AB27CE47AA66C /* UserDefaultsProtocol.swift */; };
914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; };
915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; };
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
@@ -947,7 +950,6 @@
92FE657CDFAFE3031576EB43 /* LinkNewDeviceScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED096460D7F26F10168FA33B /* LinkNewDeviceScreenViewModelProtocol.swift */; }; 92FE657CDFAFE3031576EB43 /* LinkNewDeviceScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED096460D7F26F10168FA33B /* LinkNewDeviceScreenViewModelProtocol.swift */; };
9312F5A17AE59A9E910C51D6 /* NotificationItemProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840182D7A61402D5947DE094 /* NotificationItemProxyMock.swift */; }; 9312F5A17AE59A9E910C51D6 /* NotificationItemProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840182D7A61402D5947DE094 /* NotificationItemProxyMock.swift */; };
9322949BFCA6278921085862 /* DeactivateAccountScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664D3C710B4A12CE4E623645 /* DeactivateAccountScreenModels.swift */; }; 9322949BFCA6278921085862 /* DeactivateAccountScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664D3C710B4A12CE4E623645 /* DeactivateAccountScreenModels.swift */; };
9331608392D42EF465A8E710 /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */; };
934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */; }; 934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */; };
937985546F708339711ECDFC /* ComposerToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */; }; 937985546F708339711ECDFC /* ComposerToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */; };
93A549135E6C027A0D823BFE /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 385D4C28F9DC5CF53BD9ECDB /* DeviceKit */; }; 93A549135E6C027A0D823BFE /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 385D4C28F9DC5CF53BD9ECDB /* DeviceKit */; };
@@ -971,6 +973,7 @@
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */; }; 9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */; };
95B690EA99A3385D4B8A593D /* NotificationToneManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94A6A57FE7E71F7605070AA /* NotificationToneManager.swift */; }; 95B690EA99A3385D4B8A593D /* NotificationToneManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94A6A57FE7E71F7605070AA /* NotificationToneManager.swift */; };
95E7B236F7116CACE05A6BC9 /* BlockedUsersScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */; }; 95E7B236F7116CACE05A6BC9 /* BlockedUsersScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */; };
95ED28978572AD07F0D975C8 /* AccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C071F3013E8C6DAC7FB768 /* AccountSettings.swift */; };
9603EEF6DE980BB1D15D4707 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A3E8741D199CD1A37F4CBF /* UIView.swift */; }; 9603EEF6DE980BB1D15D4707 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A3E8741D199CD1A37F4CBF /* UIView.swift */; };
962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */; }; 962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */; };
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; }; 964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
@@ -1023,6 +1026,7 @@
9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */; }; 9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */; };
9EF72884B74BC39B01640098 /* BugReportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27DF257F5D968E5DD719583C /* BugReportTests.swift */; }; 9EF72884B74BC39B01640098 /* BugReportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27DF257F5D968E5DD719583C /* BugReportTests.swift */; };
9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; }; 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; };
9F51563FBDD578F37020C852 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07204157037AB27CE47AA66C /* UserDefaultsProtocol.swift */; };
9F8BEA86540D8980BDD7C176 /* AuthenticationStartScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3AB4D399D39FBD78119011 /* AuthenticationStartScreenModels.swift */; }; 9F8BEA86540D8980BDD7C176 /* AuthenticationStartScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE3AB4D399D39FBD78119011 /* AuthenticationStartScreenModels.swift */; };
9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */; }; 9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */; };
9FBE1FB20171012260A32492 /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */; }; 9FBE1FB20171012260A32492 /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */; };
@@ -1112,13 +1116,13 @@
AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; }; AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; };
ABD29E06DD1224812E750AF8 /* ReadReceiptCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D75941CBD7D336F831924EC /* ReadReceiptCell.swift */; }; ABD29E06DD1224812E750AF8 /* ReadReceiptCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D75941CBD7D336F831924EC /* ReadReceiptCell.swift */; };
AC1DB27A4134470846BE49F6 /* UserProfileScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD116096CAA9139B95EEA9C /* UserProfileScreenViewModel.swift */; }; AC1DB27A4134470846BE49F6 /* UserProfileScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD116096CAA9139B95EEA9C /* UserProfileScreenViewModel.swift */; };
AC23453E4BBDA87031F6E478 /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004397AC54CAE108B6E2385D /* TrackedUserDefaults.swift */; };
AC3C3D6D4AD31F13EE987390 /* TraceLogPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7149BDDE47F8AD104E644E2 /* TraceLogPack.swift */; }; AC3C3D6D4AD31F13EE987390 /* TraceLogPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7149BDDE47F8AD104E644E2 /* TraceLogPack.swift */; };
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; }; AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; };
AC7AA215D60FBC307F984028 /* Consumable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127A57D053CE8C87B5EFB089 /* Consumable.swift */; }; AC7AA215D60FBC307F984028 /* Consumable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127A57D053CE8C87B5EFB089 /* Consumable.swift */; };
AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */; }; AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */; };
AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; }; AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; };
AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */; }; AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */; };
ADC820847A91C9939E269B24 /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */; };
AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */; }; AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */; };
AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */; }; AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */; };
AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */; }; AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */; };
@@ -1128,10 +1132,12 @@
AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */; }; AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */; };
AF4510502727E2ABC326C5FD /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = BDB0DD6E869B4764958CD7AB /* test_animated_image.gif */; }; AF4510502727E2ABC326C5FD /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = BDB0DD6E869B4764958CD7AB /* test_animated_image.gif */; };
AF640383EC85741D33F7558F /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100DA305FE28BB3B6AEDE1FD /* UserSettings.swift */; }; AF640383EC85741D33F7558F /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100DA305FE28BB3B6AEDE1FD /* UserSettings.swift */; };
AF75E5CF932D80EAD578E02E /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3994D186AC9893BEE458ECF /* VolatileUserDefaults.swift */; };
AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; }; AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; };
AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */; }; AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */; };
B004A08BE32F06832BF41CFC /* RoomDetailsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3674212CAB6C5143DD437AC4 /* RoomDetailsScreenHook.swift */; }; B004A08BE32F06832BF41CFC /* RoomDetailsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3674212CAB6C5143DD437AC4 /* RoomDetailsScreenHook.swift */; };
B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */; }; B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */; };
B050F3280B97071EC0158CD2 /* AccountUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */; };
B0CB16349B96262AA65A04AF /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; }; B0CB16349B96262AA65A04AF /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; };
B1088417801A962BA861C13F /* RoomPowerLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */; }; B1088417801A962BA861C13F /* RoomPowerLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */; };
B10F7D5C237417DA160F4603 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */; }; B10F7D5C237417DA160F4603 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */; };
@@ -1189,6 +1195,7 @@
BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; };
BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; }; BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; };
BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; }; BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; };
BB5467A56070EBD1C9A8FCF0 /* AccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C071F3013E8C6DAC7FB768 /* AccountSettings.swift */; };
BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; }; BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; };
BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; }; BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; };
BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; }; BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; };
@@ -1308,7 +1315,6 @@
CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */; }; CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */; };
CDAE3A37D4DF136F9D07DB61 /* RoomChangeRolesScreenSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF710CB1C31F8938EAA3A7D /* RoomChangeRolesScreenSection.swift */; }; CDAE3A37D4DF136F9D07DB61 /* RoomChangeRolesScreenSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF710CB1C31F8938EAA3A7D /* RoomChangeRolesScreenSection.swift */; };
CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; }; CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
CDD76A7D42E1B47F7E423AA8 /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2F56C9FFE8D55375CED9741 /* VolatileUserDefaults.swift */; };
CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; }; CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
CE23FE7F463AD5C7D80353AA /* RoomThreadListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */; }; CE23FE7F463AD5C7D80353AA /* RoomThreadListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */; };
CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */; }; CE3B7FC34FB2C279AAA5EA01 /* AVMetadataMachineReadableCodeObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */; };
@@ -1337,6 +1343,7 @@
D16B3134A7FF4FBA0749014A /* AuthenticationClassicAppAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C45578F406698388B97C07 /* AuthenticationClassicAppAccountView.swift */; }; D16B3134A7FF4FBA0749014A /* AuthenticationClassicAppAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C45578F406698388B97C07 /* AuthenticationClassicAppAccountView.swift */; };
D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */; }; D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */; };
D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; }; D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; };
D19E6DA46819E0807E7F00B4 /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004397AC54CAE108B6E2385D /* TrackedUserDefaults.swift */; };
D1C942421F607285C50FB792 /* SearchServiceSDKMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF5721148A5D59B476BA976 /* SearchServiceSDKMock.swift */; }; D1C942421F607285C50FB792 /* SearchServiceSDKMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF5721148A5D59B476BA976 /* SearchServiceSDKMock.swift */; };
D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; }; D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; };
D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; }; D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; };
@@ -1488,7 +1495,6 @@
E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */; }; E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */; };
EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; };
EA2FECCD9E00D9784AC6017D /* PhishingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB07F03461023BC39C730922 /* PhishingDetector.swift */; }; EA2FECCD9E00D9784AC6017D /* PhishingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB07F03461023BC39C730922 /* PhishingDetector.swift */; };
EA4848108A6FE53A4085C9B1 /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2F56C9FFE8D55375CED9741 /* VolatileUserDefaults.swift */; };
EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; }; EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; };
EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; }; EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; };
EA8D941771E762A5D3D7FA0D /* FileMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */; }; EA8D941771E762A5D3D7FA0D /* FileMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */; };
@@ -1527,6 +1533,7 @@
EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; }; EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; };
EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; }; EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; };
EF890DEF0479E66548F2BA23 /* AppLockTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */; }; EF890DEF0479E66548F2BA23 /* AppLockTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */; };
EFB3033FE782773D4F105681 /* AccountUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */; };
EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */; }; EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */; };
EFC4CCCF9D22FFA7D542693A /* NotificationTone.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF08D6FC1919CB804A9191E8 /* NotificationTone.swift */; }; EFC4CCCF9D22FFA7D542693A /* NotificationTone.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF08D6FC1919CB804A9191E8 /* NotificationTone.swift */; };
EFF735EC040BEB669AFBAB50 /* LeaveSpaceHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75B3CE05643C7791D46AC54B /* LeaveSpaceHandleProxy.swift */; }; EFF735EC040BEB669AFBAB50 /* LeaveSpaceHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75B3CE05643C7791D46AC54B /* LeaveSpaceHandleProxy.swift */; };
@@ -1621,6 +1628,7 @@
FDE47D4686BA0F86BB584633 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 3262F08E1C3483C22A7A319F /* Compound */; }; FDE47D4686BA0F86BB584633 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 3262F08E1C3483C22A7A319F /* Compound */; };
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; }; FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; };
FE578B12750E5E602D62B365 /* ComposerDisabledView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC4B431B0117BDEE697DB4A /* ComposerDisabledView.swift */; }; FE578B12750E5E602D62B365 /* ComposerDisabledView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC4B431B0117BDEE697DB4A /* ComposerDisabledView.swift */; };
FE81E0ADE56876A78FA3F2D2 /* VolatileUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3994D186AC9893BEE458ECF /* VolatileUserDefaults.swift */; };
FE9A5D4715C7AB68682C030C /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */; }; FE9A5D4715C7AB68682C030C /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */; };
FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */; }; FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */; };
FEF0E0D2EDB8A4A9FE1842EE /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = D48D415C7A4284DEBEB34924 /* portrait_test_video.mp4 */; }; FEF0E0D2EDB8A4A9FE1842EE /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = D48D415C7A4284DEBEB34924 /* portrait_test_video.mp4 */; };
@@ -1763,6 +1771,7 @@
002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreen.swift; sourceTree = "<group>"; }; 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreen.swift; sourceTree = "<group>"; };
00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = "<group>"; }; 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = "<group>"; };
002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthConfiguration.swift; sourceTree = "<group>"; }; 002DE5E9625122F37DE5F020 /* OAuthConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthConfiguration.swift; sourceTree = "<group>"; };
004397AC54CAE108B6E2385D /* TrackedUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackedUserDefaults.swift; sourceTree = "<group>"; };
007C16779FDCF10DA4F1A510 /* LinkNewDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceService.swift; sourceTree = "<group>"; }; 007C16779FDCF10DA4F1A510 /* LinkNewDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceService.swift; sourceTree = "<group>"; };
008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModelProtocol.swift; sourceTree = "<group>"; };
00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = "<group>"; }; 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = "<group>"; };
@@ -1811,6 +1820,7 @@
06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenModels.swift; sourceTree = "<group>"; }; 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenModels.swift; sourceTree = "<group>"; };
06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManagerProtocol.swift; sourceTree = "<group>"; }; 06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManagerProtocol.swift; sourceTree = "<group>"; };
06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenCoordinator.swift; sourceTree = "<group>"; }; 06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenCoordinator.swift; sourceTree = "<group>"; };
07204157037AB27CE47AA66C /* UserDefaultsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsProtocol.swift; sourceTree = "<group>"; };
0724EBDFE8BB4C9E5547C57D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; }; 0724EBDFE8BB4C9E5547C57D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsChatType.swift; sourceTree = "<group>"; }; 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsChatType.swift; sourceTree = "<group>"; };
077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = "<group>"; }; 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = "<group>"; };
@@ -1844,7 +1854,6 @@
0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenCoordinator.swift; sourceTree = "<group>"; }; 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenCoordinator.swift; sourceTree = "<group>"; };
0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; }; 0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
0CBB0B65E5C1686700EF1276 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/SAS.strings; sourceTree = "<group>"; }; 0CBB0B65E5C1686700EF1276 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/SAS.strings; sourceTree = "<group>"; };
0CCA4547BE58E17899E95CDE /* UserDefaultsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsProtocol.swift; sourceTree = "<group>"; };
0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
0CD63A653BCA2C8112654B19 /* SearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScreenModels.swift; sourceTree = "<group>"; }; 0CD63A653BCA2C8112654B19 /* SearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScreenModels.swift; sourceTree = "<group>"; };
0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = "<group>"; }; 0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = "<group>"; };
@@ -1872,7 +1881,6 @@
1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; }; 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderProtocol.swift; sourceTree = "<group>"; }; 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderProtocol.swift; sourceTree = "<group>"; };
10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackedUserDefaults.swift; sourceTree = "<group>"; };
10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenModels.swift; sourceTree = "<group>"; }; 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenModels.swift; sourceTree = "<group>"; };
10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenSelectedItem.swift; sourceTree = "<group>"; }; 10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenSelectedItem.swift; sourceTree = "<group>"; };
11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@@ -2107,6 +2115,7 @@
3674212CAB6C5143DD437AC4 /* RoomDetailsScreenHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenHook.swift; sourceTree = "<group>"; }; 3674212CAB6C5143DD437AC4 /* RoomDetailsScreenHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenHook.swift; sourceTree = "<group>"; };
369236171C351AB8C70BB161 /* preview_video.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_video.jpg; sourceTree = "<group>"; }; 369236171C351AB8C70BB161 /* preview_video.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_video.jpg; sourceTree = "<group>"; };
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountUserDefaults.swift; sourceTree = "<group>"; };
36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = "<group>"; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = "<group>"; };
3747C96188856006F784BF49 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ko; path = ko.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 3747C96188856006F784BF49 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ko; path = ko.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; };
@@ -2946,6 +2955,7 @@
C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingFlowCoordinator.swift; sourceTree = "<group>"; }; C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingFlowCoordinator.swift; sourceTree = "<group>"; };
C33B3F17996DFDF5F0181512 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = "<group>"; }; C33B3F17996DFDF5F0181512 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = "<group>"; };
C352359663A0E52BA20761EE /* LoadableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableImage.swift; sourceTree = "<group>"; }; C352359663A0E52BA20761EE /* LoadableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableImage.swift; sourceTree = "<group>"; };
C3994D186AC9893BEE458ECF /* VolatileUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolatileUserDefaults.swift; sourceTree = "<group>"; };
C3C2316BADD6C1119C1FA229 /* NativeCallSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeCallSystem.swift; sourceTree = "<group>"; }; C3C2316BADD6C1119C1FA229 /* NativeCallSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeCallSystem.swift; sourceTree = "<group>"; };
C454F35D8884C0A952FF2F84 /* LiveLocationSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationSheet.swift; sourceTree = "<group>"; }; C454F35D8884C0A952FF2F84 /* LiveLocationSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationSheet.swift; sourceTree = "<group>"; };
C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManagerProtocol.swift; sourceTree = "<group>"; }; C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManagerProtocol.swift; sourceTree = "<group>"; };
@@ -3163,6 +3173,7 @@
E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProvider.swift; sourceTree = "<group>"; }; E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProvider.swift; sourceTree = "<group>"; };
E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = "<group>"; }; E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = "<group>"; };
E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxyMock.swift; sourceTree = "<group>"; }; E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxyMock.swift; sourceTree = "<group>"; };
E96792E7EE6742172DA3A35E /* AccountUserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountUserDefaultsTests.swift; sourceTree = "<group>"; };
E9773983346838AABFAA914D /* UserSessionHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionHook.swift; sourceTree = "<group>"; }; E9773983346838AABFAA914D /* UserSessionHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionHook.swift; sourceTree = "<group>"; };
E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = "<group>"; }; E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = "<group>"; };
E994322F10D20ECE68683683 /* GalleryRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryRoomTimelineItem.swift; sourceTree = "<group>"; }; E994322F10D20ECE68683683 /* GalleryRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -3200,6 +3211,7 @@
ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = "<group>"; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = "<group>"; };
EDDE826EAB1BAB80C1104980 /* SpaceFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceFlowCoordinator.swift; sourceTree = "<group>"; }; EDDE826EAB1BAB80C1104980 /* SpaceFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceFlowCoordinator.swift; sourceTree = "<group>"; };
EDE997F400545F3265935B53 /* UserSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsTests.swift; sourceTree = "<group>"; };
EDF6E8208542BE7A02A94939 /* PresentationColorSchemeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentationColorSchemeModifier.swift; sourceTree = "<group>"; }; EDF6E8208542BE7A02A94939 /* PresentationColorSchemeModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentationColorSchemeModifier.swift; sourceTree = "<group>"; };
EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; };
EE61568A225F7AA068583AA7 /* SignallingTimelineItemProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignallingTimelineItemProviderMock.swift; sourceTree = "<group>"; }; EE61568A225F7AA068583AA7 /* SignallingTimelineItemProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignallingTimelineItemProviderMock.swift; sourceTree = "<group>"; };
@@ -3231,7 +3243,6 @@
F2B94F1B0B5D9D42B15AA6E8 /* ChatsTabFlowCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTabFlowCoordinatorStateMachine.swift; sourceTree = "<group>"; }; F2B94F1B0B5D9D42B15AA6E8 /* ChatsTabFlowCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTabFlowCoordinatorStateMachine.swift; sourceTree = "<group>"; };
F2DC502B1A566E99969D34DD /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; }; F2DC502B1A566E99969D34DD /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = "<group>"; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = "<group>"; };
F2F56C9FFE8D55375CED9741 /* VolatileUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolatileUserDefaults.swift; sourceTree = "<group>"; };
F3082001D373607455CB08A1 /* QRCodeErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeErrorView.swift; sourceTree = "<group>"; }; F3082001D373607455CB08A1 /* QRCodeErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeErrorView.swift; sourceTree = "<group>"; };
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = "<group>"; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = "<group>"; };
F320003F490B11F808ECC5E9 /* JoinedMembersBadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedMembersBadgeView.swift; sourceTree = "<group>"; }; F320003F490B11F808ECC5E9 /* JoinedMembersBadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedMembersBadgeView.swift; sourceTree = "<group>"; };
@@ -3264,6 +3275,7 @@
F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevel.swift; sourceTree = "<group>"; }; F7E247E29C7A0E421DB839D7 /* RoomPowerLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevel.swift; sourceTree = "<group>"; };
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; };
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = "<group>"; }; F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = "<group>"; };
F8C071F3013E8C6DAC7FB768 /* AccountSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettings.swift; sourceTree = "<group>"; };
F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreen.swift; sourceTree = "<group>"; }; F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreen.swift; sourceTree = "<group>"; };
F91AC45CDDF85E946391CA5C /* RoomThreadListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModel.swift; sourceTree = "<group>"; }; F91AC45CDDF85E946391CA5C /* RoomThreadListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModel.swift; sourceTree = "<group>"; };
F933BB25FC426D5C67E1D812 /* TimelineControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerMock.swift; sourceTree = "<group>"; }; F933BB25FC426D5C67E1D812 /* TimelineControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerMock.swift; sourceTree = "<group>"; };
@@ -5267,6 +5279,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
12D0FBA1FE29833A915B77AE /* AccountProviderTests.swift */, 12D0FBA1FE29833A915B77AE /* AccountProviderTests.swift */,
E96792E7EE6742172DA3A35E /* AccountUserDefaultsTests.swift */,
58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */, 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */,
C687844F60BFF532D49A994C /* AnalyticsTests.swift */, C687844F60BFF532D49A994C /* AnalyticsTests.swift */,
E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */, E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */,
@@ -5399,6 +5412,7 @@
71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */, 71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */,
4FA29BAE9B0F2D90E57B261C /* UserSessionFlowCoordinatorTests.swift */, 4FA29BAE9B0F2D90E57B261C /* UserSessionFlowCoordinatorTests.swift */,
F5F7E6F5D5A54C68DC2EDD71 /* UserSessionStoreTests.swift */, F5F7E6F5D5A54C68DC2EDD71 /* UserSessionStoreTests.swift */,
EDE997F400545F3265935B53 /* UserSettingsTests.swift */,
283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */, 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */,
AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */, AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */,
D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */, D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */,
@@ -5908,6 +5922,17 @@
path = HTMLParsing; path = HTMLParsing;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
8FB4475AADA10756AFB4370D /* Storage */ = {
isa = PBXGroup;
children = (
36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */,
004397AC54CAE108B6E2385D /* TrackedUserDefaults.swift */,
07204157037AB27CE47AA66C /* UserDefaultsProtocol.swift */,
C3994D186AC9893BEE458ECF /* VolatileUserDefaults.swift */,
);
path = Storage;
sourceTree = "<group>";
};
90DC2E28718955ED87AD1456 /* CreatePollScreen */ = { 90DC2E28718955ED87AD1456 /* CreatePollScreen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -6929,6 +6954,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A67BCEFE35F8D00CADF108C9 /* AccountProvider.swift */, A67BCEFE35F8D00CADF108C9 /* AccountProvider.swift */,
F8C071F3013E8C6DAC7FB768 /* AccountSettings.swift */,
FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */, FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */,
353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */, 353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */,
0FD22AEFFA20065494ED2333 /* AppAppearance.swift */, 0FD22AEFFA20065494ED2333 /* AppAppearance.swift */,
@@ -6941,10 +6967,8 @@
8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */, 8FC598338E7CF41107293AB5 /* RageshakeConfiguration.swift */,
69A05E85E4872C3221C5C287 /* RemotePreference.swift */, 69A05E85E4872C3221C5C287 /* RemotePreference.swift */,
095B8ED0CA87F4A0A4858719 /* SearchBreadcrumb.swift */, 095B8ED0CA87F4A0A4858719 /* SearchBreadcrumb.swift */,
10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */,
0CCA4547BE58E17899E95CDE /* UserDefaultsProtocol.swift */,
100DA305FE28BB3B6AEDE1FD /* UserSettings.swift */, 100DA305FE28BB3B6AEDE1FD /* UserSettings.swift */,
F2F56C9FFE8D55375CED9741 /* VolatileUserDefaults.swift */, 8FB4475AADA10756AFB4370D /* Storage */,
); );
path = Settings; path = Settings;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -8275,6 +8299,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
75C1AFACE6C0DEA18F16456C /* AccountProvider.swift in Sources */, 75C1AFACE6C0DEA18F16456C /* AccountProvider.swift in Sources */,
BB5467A56070EBD1C9A8FCF0 /* AccountSettings.swift in Sources */,
B050F3280B97071EC0158CD2 /* AccountUserDefaults.swift in Sources */,
CA2BFC5504AD91A028CFA45B /* AnalyticsConfiguration.swift in Sources */, CA2BFC5504AD91A028CFA45B /* AnalyticsConfiguration.swift in Sources */,
4E9ED3E6E979C6C7FEC1D011 /* AnalyticsConsentState.swift in Sources */, 4E9ED3E6E979C6C7FEC1D011 /* AnalyticsConsentState.swift in Sources */,
68C3AF257678F6E7BB238C3F /* AppAppearance.swift in Sources */, 68C3AF257678F6E7BB238C3F /* AppAppearance.swift in Sources */,
@@ -8352,15 +8378,15 @@
AC3C3D6D4AD31F13EE987390 /* TraceLogPack.swift in Sources */, AC3C3D6D4AD31F13EE987390 /* TraceLogPack.swift in Sources */,
B81840E45D8746A4692DA774 /* Tracing.swift in Sources */, B81840E45D8746A4692DA774 /* Tracing.swift in Sources */,
2D45A04699BB6BA3B3A0CB9A /* TracingHook.swift in Sources */, 2D45A04699BB6BA3B3A0CB9A /* TracingHook.swift in Sources */,
6BEB10499149444909EBE42F /* TrackedUserDefaults.swift in Sources */, D19E6DA46819E0807E7F00B4 /* TrackedUserDefaults.swift in Sources */,
45D6DC594816288983627484 /* UITestsScreenIdentifier.swift in Sources */, 45D6DC594816288983627484 /* UITestsScreenIdentifier.swift in Sources */,
281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */, 281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */,
06B55882911B4BF5B14E9851 /* URL.swift in Sources */, 06B55882911B4BF5B14E9851 /* URL.swift in Sources */,
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */, D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */,
34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */, 34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */,
1B1404DD4BB2C5079B074210 /* UserDefaultsProtocol.swift in Sources */, 90F7C2C3DF76B3B00B58CB57 /* UserDefaultsProtocol.swift in Sources */,
D61FCF6ABC1490F630E76AEC /* UserSettings.swift in Sources */, D61FCF6ABC1490F630E76AEC /* UserSettings.swift in Sources */,
28A494A66D0F21EC1EC4EB11 /* VolatileUserDefaults.swift in Sources */, AF75E5CF932D80EAD578E02E /* VolatileUserDefaults.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -8370,6 +8396,7 @@
files = ( files = (
C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */, C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */,
A1A16FEF565ED7972591988B /* AccountProviderTests.swift in Sources */, A1A16FEF565ED7972591988B /* AccountProviderTests.swift in Sources */,
106E3126B0C49231381B5B80 /* AccountUserDefaultsTests.swift in Sources */,
A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */, A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */,
890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */, 890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */,
8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */, 8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */,
@@ -8525,6 +8552,7 @@
73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */, 73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */,
627139A3D79F032BA81E3A53 /* UserSessionFlowCoordinatorTests.swift in Sources */, 627139A3D79F032BA81E3A53 /* UserSessionFlowCoordinatorTests.swift in Sources */,
E3E1B656F2E8F2D8075F6558 /* UserSessionStoreTests.swift in Sources */, E3E1B656F2E8F2D8075F6558 /* UserSessionStoreTests.swift in Sources */,
51DBB7D725080FDAA4AB1412 /* UserSettingsTests.swift in Sources */,
21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */, 21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */,
44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */, 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */,
A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */, A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */,
@@ -8568,6 +8596,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3A363617757E6838AC3D15FB /* AccountProvider.swift in Sources */, 3A363617757E6838AC3D15FB /* AccountProvider.swift in Sources */,
95ED28978572AD07F0D975C8 /* AccountSettings.swift in Sources */,
708B77D5E65BB48D44732236 /* AccountUserDefaults.swift in Sources */,
C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */, C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */,
585DCA0487A0A6F4E59EF5CA /* AnalyticsConsentState.swift in Sources */, 585DCA0487A0A6F4E59EF5CA /* AnalyticsConsentState.swift in Sources */,
88887E40301FF0543ED5B59F /* AppAppearance.swift in Sources */, 88887E40301FF0543ED5B59F /* AppAppearance.swift in Sources */,
@@ -8606,13 +8636,13 @@
A5FD8284744E2FECFC842FC1 /* TraceLogPack.swift in Sources */, A5FD8284744E2FECFC842FC1 /* TraceLogPack.swift in Sources */,
89DF67AECBF9D0EE0DDB7737 /* Tracing.swift in Sources */, 89DF67AECBF9D0EE0DDB7737 /* Tracing.swift in Sources */,
51263FC33CC961A14F5D6BCA /* TracingHook.swift in Sources */, 51263FC33CC961A14F5D6BCA /* TracingHook.swift in Sources */,
9331608392D42EF465A8E710 /* TrackedUserDefaults.swift in Sources */, 879013B1A7DA779C7E0C56A4 /* TrackedUserDefaults.swift in Sources */,
03BD83E8BDD23AE059802E0D /* UITestsScreenIdentifier.swift in Sources */, 03BD83E8BDD23AE059802E0D /* UITestsScreenIdentifier.swift in Sources */,
26252AA9AED64010788F4C26 /* UIView.swift in Sources */, 26252AA9AED64010788F4C26 /* UIView.swift in Sources */,
66E9202BED03B5BB00E812A1 /* URL.swift in Sources */, 66E9202BED03B5BB00E812A1 /* URL.swift in Sources */,
29E411E37D3FBF3899B3ED69 /* UserDefaultsProtocol.swift in Sources */, 9F51563FBDD578F37020C852 /* UserDefaultsProtocol.swift in Sources */,
452507BCE97B3EA0F24E206E /* UserSettings.swift in Sources */, 452507BCE97B3EA0F24E206E /* UserSettings.swift in Sources */,
CDD76A7D42E1B47F7E423AA8 /* VolatileUserDefaults.swift in Sources */, 0B30DC7D9D445C405ADCB5FA /* VolatileUserDefaults.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -8641,6 +8671,8 @@
28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */, 28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */,
2538350683F421AB620AA950 /* AccessibleLongPress.swift in Sources */, 2538350683F421AB620AA950 /* AccessibleLongPress.swift in Sources */,
03E9750B2F994A79FA1296A1 /* AccountProvider.swift in Sources */, 03E9750B2F994A79FA1296A1 /* AccountProvider.swift in Sources */,
4A7957D034F5D96909127881 /* AccountSettings.swift in Sources */,
EFB3033FE782773D4F105681 /* AccountUserDefaults.swift in Sources */,
21215E17C9908F1EBF621BE0 /* ActiveCallTimelineItemView.swift in Sources */, 21215E17C9908F1EBF621BE0 /* ActiveCallTimelineItemView.swift in Sources */,
09E1A358EA4205480AEF4698 /* AdvancedSettingsScreen.swift in Sources */, 09E1A358EA4205480AEF4698 /* AdvancedSettingsScreen.swift in Sources */,
34ADC506C929D10B138EBA51 /* AdvancedSettingsScreenCoordinator.swift in Sources */, 34ADC506C929D10B138EBA51 /* AdvancedSettingsScreenCoordinator.swift in Sources */,
@@ -9678,7 +9710,7 @@
6E44638FDF7D4B0F80EFA7EA /* TraceLogPack.swift in Sources */, 6E44638FDF7D4B0F80EFA7EA /* TraceLogPack.swift in Sources */,
126CBCF5B0145FA1377C1316 /* Tracing.swift in Sources */, 126CBCF5B0145FA1377C1316 /* Tracing.swift in Sources */,
E010DDE938032D3B8E84CC35 /* TracingHook.swift in Sources */, E010DDE938032D3B8E84CC35 /* TracingHook.swift in Sources */,
ADC820847A91C9939E269B24 /* TrackedUserDefaults.swift in Sources */, AC23453E4BBDA87031F6E478 /* TrackedUserDefaults.swift in Sources */,
298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */, 298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */,
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */, 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */,
A37EED79941AD3B7140B3822 /* UIDevice.swift in Sources */, A37EED79941AD3B7140B3822 /* UIDevice.swift in Sources */,
@@ -9696,7 +9728,7 @@
34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */, 34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */,
D8459AAD6969B1431ECBE990 /* UnsupportedRoomTimelineView.swift in Sources */, D8459AAD6969B1431ECBE990 /* UnsupportedRoomTimelineView.swift in Sources */,
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */, 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */,
8CFB8BB99F25FA34B6C6BE86 /* UserDefaultsProtocol.swift in Sources */, 780C0394F8A10C4BCAC85DDC /* UserDefaultsProtocol.swift in Sources */,
7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */, 7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */,
A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */, A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */,
3982C505960006B341CFD0C6 /* UserDetailsEditScreenModels.swift in Sources */, 3982C505960006B341CFD0C6 /* UserDetailsEditScreenModels.swift in Sources */,
@@ -9759,7 +9791,7 @@
024E70451A7CD9E4E034D8A9 /* VoiceMessageRoomTimelineItem.swift in Sources */, 024E70451A7CD9E4E034D8A9 /* VoiceMessageRoomTimelineItem.swift in Sources */,
1224084B7E289E0830BA2C54 /* VoiceMessageRoomTimelineView.swift in Sources */, 1224084B7E289E0830BA2C54 /* VoiceMessageRoomTimelineView.swift in Sources */,
1CA094038D4D036A6F0A1314 /* VoiceMessageTrashButton.swift in Sources */, 1CA094038D4D036A6F0A1314 /* VoiceMessageTrashButton.swift in Sources */,
EA4848108A6FE53A4085C9B1 /* VolatileUserDefaults.swift in Sources */, FE81E0ADE56876A78FA3F2D2 /* VolatileUserDefaults.swift in Sources */,
CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */, CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */,
63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */, 63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */,
B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */, B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */,
@@ -10438,7 +10470,7 @@
IS_NIGHTLY_BUILD = NO; IS_NIGHTLY_BUILD = NO;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)"; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 14.5; MACOSX_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 26.10.0; MARKETING_VERSION = 26.10.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCTION_APP_NAME = Element; PRODUCTION_APP_NAME = Element;
@@ -10520,7 +10552,7 @@
IS_NIGHTLY_BUILD = NO; IS_NIGHTLY_BUILD = NO;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)"; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 14.5; MACOSX_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 26.10.0; MARKETING_VERSION = 26.10.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
@@ -467,14 +467,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
MXLog.info("The app was upgraded from \(oldVersion) to \(newVersion)") 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) { if oldVersion < Version(1, 6, 7) {
Tracing.deleteLogFiles(in: Tracing.legacyLogsDirectory) Tracing.deleteLogFiles(in: Tracing.legacyLogsDirectory)
MXLog.info("Migrating to v1.6.7, log files have been wiped") MXLog.info("Migrating to v1.6.7, log files have been wiped")
@@ -498,6 +490,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
await userSession.clientProxy.optimizeStores() await userSession.clientProxy.optimizeStores()
MXLog.info("Finished optimizing client stores.") 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) { if oldVersion < Version(25, 6, 0) {
MXLog.info("Migrating to version 25.06.0, migrating timeline media settings to account data.") MXLog.info("Migrating to version 25.06.0, migrating timeline media settings to account data.")
performSettingsToAccountDataMigration(userSession: userSession) performSettingsToAccountDataMigration(userSession: userSession)
@@ -518,6 +516,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
appSettings.hasSignedInBefore = true 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 userSessionMigrationsOldVersion = nil
} }
@@ -863,7 +867,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
userSessionStore.logout(userSession: userSession) userSessionStore.logout(userSession: userSession)
tearDownUserSession() tearDownUserSession()
appSettings.resetSessionSpecificSettings() userSession.userSettings.resetSessionSpecificSettings()
appHooks.remoteSettingsHook.reset(appSettings) appHooks.remoteSettingsHook.reset(appSettings)
// Reset analytics // 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() store.reset()
} }
func resetSessionSpecificSettings() {
MXLog.warning("Resetting the user session specific AppSettings.")
resetHasRunIdentityConfirmationOnboarding()
resetSearchBreadcrumbs()
}
// MARK: - Hooks // MARK: - Hooks
// swiftlint:disable:next function_parameter_count // swiftlint:disable:next function_parameter_count
@@ -338,9 +332,6 @@ final nonisolated class AppSettings: @unchecked Sendable {
@UserPreference(defaultValue: false) @UserPreference(defaultValue: false)
var hasRunNotificationPermissionsOnboarding: Bool var hasRunNotificationPermissionsOnboarding: Bool
@UserPreference(defaultValue: false)
var hasRunIdentityConfirmationOnboarding: Bool
@UserPreference(defaultValue: false) @UserPreference(defaultValue: false)
var hasRequestedLocationAlwaysLocationAuthorization: Bool var hasRequestedLocationAlwaysLocationAuthorization: Bool
@@ -363,12 +354,6 @@ final nonisolated class AppSettings: @unchecked Sendable {
@UserPreference(defaultValue: true) @UserPreference(defaultValue: true)
var showAllRoomListActivity: Bool 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 // MARK: - Room Screen
@UserPreference(defaultValue: AppBuildType.current == .debug) @UserPreference(defaultValue: AppBuildType.current == .debug)
@@ -482,6 +467,10 @@ final nonisolated class AppSettings: @unchecked Sendable {
self.store = store self.store = store
} }
func userSettings(for userID: String) -> UserSettings {
UserSettings(appSettings: self, accountSettings: .init(userID: userID, store: store))
}
static func volatile() -> AppSettings { static func volatile() -> AppSettings {
AppSettings(store: VolatileUserDefaults()) 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
}
}
@@ -15,6 +15,7 @@ nonisolated protocol UserDefaultsProtocol: AnyObject {
func set(_ value: Any?, forKey key: String) func set(_ value: Any?, forKey key: String)
func reset() func reset()
func dictionaryRepresentation() -> [String: Any]
} }
// MARK: - Codable handling // MARK: - Codable handling
@@ -42,4 +42,8 @@ final nonisolated class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
func reset() { func reset() {
storage = [:] storage = [:]
} }
func dictionaryRepresentation() -> [String: Any] {
storage
}
} }
@@ -6,22 +6,23 @@
// //
import Foundation import Foundation
import Macros
/// The settings for a signed in account, composed of the app wide settings and the settings /// The settings for a signed in account, composed of the app wide settings and the settings
/// specific to that account. /// specific to that account.
@dynamicMemberLookup @dynamicMemberLookup
final nonisolated class UserSettings: Sendable { final nonisolated class UserSettings: Sendable {
// TODO: @pixlwave Make this private after handling Advanced/Labs/Developer screen models.
let app: AppSettings let app: AppSettings
let account: AccountSettings private let account: AccountSettings
init(appSettings: AppSettings, accountSettings: AccountSettings) { init(appSettings: AppSettings, accountSettings: AccountSettings) {
self.app = appSettings self.app = appSettings
self.account = accountSettings self.account = accountSettings
} }
static func volatile() -> UserSettings { static func mock(userID: String = "@me:matrix.org") -> UserSettings {
let appSettings = AppSettings.volatile() AppSettings.volatile().userSettings(for: userID)
return UserSettings(appSettings: appSettings, accountSettings: .init())
} }
subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<AppSettings, Value>) -> Value { 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 { subscript<Value>(dynamicMember keyPath: KeyPath<AccountSettings, Value>) -> Value {
account[keyPath: keyPath] account[keyPath: keyPath]
} }
}
func migrateAppSettingsValueToAccountSettings(_ keyPath: KeyPath<AccountSettings, UserPreferenceKey>) {
/// Settings specific to an account. account.migrateAppSettingsValue(keyPath)
struct AccountSettings { }
// Placeholder for now, implementation to follow with a dedicated user defaults store scoped to a specific user ID.
func resetSessionSpecificSettings() {
account.reset()
}
} }
+1 -1
View File
@@ -11,7 +11,7 @@ import Foundation
struct UserSessionMockConfiguration { struct UserSessionMockConfiguration {
var clientProxy: ClientProxyProtocol = ClientProxyMock(.init()) var clientProxy: ClientProxyProtocol = ClientProxyMock(.init())
var userSettings: UserSettings = .volatile() var userSettings: UserSettings = .mock()
var contentScannerService: ContentScannerServiceProtocol? var contentScannerService: ContentScannerServiceProtocol?
} }
@@ -56,7 +56,7 @@ private struct VisualListItemLabelStyle: LabelStyle {
// MARK: - Previews // MARK: - Previews
struct VisualListItem_Previews: PreviewProvider, TestablePreview { 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 { static var testImage1: some View {
Image(systemName: "circle") Image(systemName: "circle")
@@ -405,7 +405,7 @@ struct CallScreen_Previews: PreviewProvider {
voiceOnly: false, voiceOnly: false,
colorScheme: .light), colorScheme: .light),
allowPictureInPicture: false, allowPictureInPicture: false,
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init())) analyticsService: AnalyticsServiceMock(.init()))
} }
} }
@@ -451,7 +451,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
isSpace: Bool = false, isSpace: Bool = false,
selectionMode: CreateRoomScreenSpaceSelectionMode = .editableSpacesList(preSelectedSpace: nil), selectionMode: CreateRoomScreenSpaceSelectionMode = .editableSpacesList(preSelectedSpace: nil),
isAliasAvailable: Bool = true) -> CreateRoomScreenViewModel { isAliasAvailable: Bool = true) -> CreateRoomScreenViewModel {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.knockingEnabled = isKnockingEnabled userSettings.knockingEnabled = isKnockingEnabled
let clientProxy = ClientProxyMock(.init(userIDServerName: "example.org", let clientProxy = ClientProxyMock(.init(userIDServerName: "example.org",
@@ -65,7 +65,7 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2)) clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
let userSession = UserSessionMock(.init(clientProxy: clientProxy)) let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
return CreateRoomScreenViewModel(isSpace: false, return CreateRoomScreenViewModel(isSpace: false,
spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil), spaceSelectionMode: .editableSpacesList(preSelectedSpace: nil),
@@ -103,7 +103,7 @@ struct EmojiPickerScreen: View {
@available(iOS 26.0, *) @available(iOS 26.0, *)
struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview { struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"], static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"],
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
continuation: AsyncStream<String>.makeStream().continuation) continuation: AsyncStream<String>.makeStream().continuation)
static var previews: some View { static var previews: some View {
@@ -115,7 +115,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
struct EmojiPickerScreenSheet_Previews: PreviewProvider { struct EmojiPickerScreenSheet_Previews: PreviewProvider {
static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"], static let viewModel = EmojiPickerScreenViewModel(selectedEmojis: ["😀", "😄"],
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
continuation: AsyncStream<String>.makeStream().continuation) continuation: AsyncStream<String>.makeStream().continuation)
static var previews: some View { static var previews: some View {
@@ -61,10 +61,10 @@ struct RoomListFiltersEmptyStateView_Previews: PreviewProvider, TestablePreview
VStack(spacing: 24) { VStack(spacing: 24) {
ForEach(RoomListFilter.allCases) { filter in ForEach(RoomListFilter.allCases) { filter in
RoomListFiltersEmptyStateView(state: .init(activeFilters: [filter], RoomListFiltersEmptyStateView(state: .init(activeFilters: [filter],
userSettings: .volatile())) userSettings: .mock()))
} }
RoomListFiltersEmptyStateView(state: .init(activeFilters: [.people, .favourites], RoomListFiltersEmptyStateView(state: .init(activeFilters: [.people, .favourites],
userSettings: .volatile())) userSettings: .mock()))
} }
.padding(.bottom) .padding(.bottom)
.previewLayout(.sizeThatFits) .previewLayout(.sizeThatFits)
@@ -92,10 +92,10 @@ struct RoomListFiltersView: View {
struct RoomListFiltersView_Previews: PreviewProvider, TestablePreview { struct RoomListFiltersView_Previews: PreviewProvider, TestablePreview {
static var previews: some View { static var previews: some View {
RoomListFiltersView(state: .constant(.init(userSettings: .volatile()))) RoomListFiltersView(state: .constant(.init(userSettings: .mock())))
RoomListFiltersView(state: .constant(.init(activeFilters: [.rooms, .favourites], RoomListFiltersView(state: .constant(.init(activeFilters: [.rooms, .favourites],
userSettings: .volatile()))) userSettings: .mock())))
RoomListFiltersView(state: .constant(.init(activeFilters: [.lowPriority], RoomListFiltersView(state: .constant(.init(activeFilters: [.lowPriority],
userSettings: .volatile()))) userSettings: .mock())))
} }
} }
@@ -232,7 +232,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -145,7 +145,7 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))))))) roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([])))))))
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -201,7 +201,7 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -133,7 +133,7 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview {
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -122,7 +122,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
return HomeScreenViewModel(userSession: userSession, return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: NotificationManagerMock(), notificationManager: NotificationManagerMock(),
@@ -402,7 +402,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
self.isSpace = isSpace self.isSpace = isSpace
self.customPreviewName = customPreviewName self.customPreviewName = customPreviewName
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars)) let clientProxy = ClientProxyMock(.init(hideInviteAvatars: hideInviteAvatars))
clientProxy.canJoinRoomWithReturnValue = canJoinRoom clientProxy.canJoinRoomWithReturnValue = canJoinRoom
@@ -432,7 +432,7 @@ extension LocationSharingScreenViewModel {
let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID)) let roomProxy = JoinedRoomProxyMock(.init(members: .allMembers, ownUserID: RoomMemberProxyMock.mockMe.userID))
roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxy.makeLiveLocationServiceReturnValue = liveLocationServiceMock
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
return LocationSharingScreenViewModel(interactionMode: interactionMode, return LocationSharingScreenViewModel(interactionMode: interactionMode,
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
@@ -314,7 +314,7 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -393,7 +393,7 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview {
title: "App Icon.png", title: "App Icon.png",
shouldShowCaptionWarning: true, shouldShowCaptionWarning: true,
galleryEnabled: true, galleryEnabled: true,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
timelineController: TimelineControllerMock(.init()), timelineController: TimelineControllerMock(.init()),
clientProxy: ClientProxyMock(.init()), clientProxy: ClientProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -102,6 +102,6 @@ struct AnalyticsPromptScreen_Previews: PreviewProvider, TestablePreview {
} }
static func makeViewModel(showTerms: Bool = true) -> AnalyticsPromptScreenViewModel { static func makeViewModel(showTerms: Bool = true) -> AnalyticsPromptScreenViewModel {
AnalyticsPromptScreenViewModel(termsURL: showTerms ? UserSettings.volatile().analyticsTermsURL : nil) AnalyticsPromptScreenViewModel(termsURL: showTerms ? UserSettings.mock().analyticsTermsURL : nil)
} }
} }
@@ -142,7 +142,7 @@ struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview {
userSession.sessionSecurityStatePublisher = CurrentValuePublisher<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: recoveryState)) userSession.sessionSecurityStatePublisher = CurrentValuePublisher<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: recoveryState))
return IdentityConfirmationScreenViewModel(userSession: userSession, return IdentityConfirmationScreenViewModel(userSession: userSession,
userSettings: .volatile(), userSettings: .mock(),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -289,7 +289,7 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview {
flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View { flow: SessionVerificationScreenFlow = .deviceInitiator) -> some View {
let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(), let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(),
flow: flow, flow: flow,
userSettings: .volatile(), userSettings: .mock(),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
verificationState: state) verificationState: state)
@@ -83,7 +83,7 @@ struct PinnedEventsTimelineScreen: View {
struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview { struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()), static let viewModel = PinnedEventsTimelineScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init())) analyticsService: AnalyticsServiceMock(.init()))
static let emptyTimelineViewModel = makeTimelineViewModel(timelineItems: []) static let emptyTimelineViewModel = makeTimelineViewModel(timelineItems: [])
@@ -106,7 +106,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
let eventIDs = timelineItems.compactMap { ($0 as? EventBasedTimelineItemProtocol)?.id.eventID } let eventIDs = timelineItems.compactMap { ($0 as? EventBasedTimelineItemProtocol)?.id.eventID }
let timelineController = TimelineControllerMock(.init(timelineKind: .pinned, timelineItems: timelineItems)) let timelineController = TimelineControllerMock(.init(timelineKind: .pinned, timelineItems: timelineItems))
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.messageMultiSelectEnabled = isSelecting userSettings.messageMultiSelectEnabled = isSelecting
let userSession = UserSessionMock(.init(userSettings: userSettings)) let userSession = UserSessionMock(.init(userSettings: userSettings))
@@ -117,7 +117,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -177,7 +177,7 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
return RoomDetailsEditScreenViewModel(roomProxy: roomProxy, return RoomDetailsEditScreenViewModel(roomProxy: roomProxy,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -445,7 +445,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -474,7 +474,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -513,7 +513,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
return .init(roomProxy: roomProxy, return .init(roomProxy: roomProxy,
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)), userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -852,7 +852,7 @@ extension ComposerToolbarViewModel {
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
userSettings: .volatile(), userSettings: .mock(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()))
viewModel.state.bindings.composerFocused = focused viewModel.state.bindings.composerFocused = focused
@@ -81,7 +81,7 @@ struct RoomAttachmentPicker_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel() static let viewModel = makeViewModel()
static func makeViewModel() -> ComposerToolbarViewModel { static func makeViewModel() -> ComposerToolbarViewModel {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
return ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()), return ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: WysiwygComposerViewModel(), wysiwygViewModel: WysiwygComposerViewModel(),
@@ -395,7 +395,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
powerLevelsConfiguration: .init(canUserSendMessage: canSendMessage))) powerLevelsConfiguration: .init(canUserSendMessage: canSendMessage)))
let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.messageMultiSelectEnabled = isSelecting userSettings.messageMultiSelectEnabled = isSelecting
let userSession = UserSessionMock(.init(userSettings: userSettings)) let userSession = UserSessionMock(.init(userSettings: userSettings))
@@ -629,31 +629,31 @@ struct SearchScreen_Previews: PreviewProvider, TestablePreview {
clientProxy: makeClientProxy(), clientProxy: makeClientProxy(),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.volatile()) userSettings: UserSettings.mock())
static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(), clientProxy: makeClientProxy(),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
initialSearchQuery: "John Doe") initialSearchQuery: "John Doe")
static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
clientProxy: makeClientProxy(), clientProxy: makeClientProxy(),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation") initialSearchQuery: "Foundation")
static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)), clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation", initialSearchQuery: "Foundation",
initialSearchMode: .messages) initialSearchMode: .messages)
static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))), static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)), clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
initialSearchQuery: "Foundation", initialSearchQuery: "Foundation",
initialSearchMode: .messages) initialSearchMode: .messages)
@@ -708,7 +708,7 @@ struct SearchScreen_Previews: PreviewProvider, TestablePreview {
} }
private static func makeUserSettings(breadcrumbs: [SearchBreadcrumb]) -> UserSettings { private static func makeUserSettings(breadcrumbs: [SearchBreadcrumb]) -> UserSettings {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.searchBreadcrumbs = breadcrumbs userSettings.searchBreadcrumbs = breadcrumbs
return userSettings return userSettings
} }
@@ -235,7 +235,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
joinRule: .invite)), joinRule: .invite)),
clientProxy: ClientProxyMock(.init()), clientProxy: ClientProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .volatile(), userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -245,7 +245,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .volatile(), userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -253,11 +253,11 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
joinRule: .public)), joinRule: .public)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .volatile(), userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static let singleSpaceMembersViewModel = { static let singleSpaceMembersViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let space = [SpaceServiceRoom].mockSingleRoom[0] let space = [SpaceServiceRoom].mockSingleRoom[0]
@@ -274,7 +274,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
}() }()
static let multipleSpacesMembersViewModel = { static let multipleSpacesMembersViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let spaces = [SpaceServiceRoom].mockJoinedSpaces let spaces = [SpaceServiceRoom].mockJoinedSpaces
@@ -291,7 +291,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
}() }()
static let askToJoinViewModel = { static let askToJoinViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.knockingEnabled = true userSettings.knockingEnabled = true
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -306,7 +306,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
}() }()
static let singleAskToJoinSpaceMembersViewModel = { static let singleAskToJoinSpaceMembersViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.knockingEnabled = true userSettings.knockingEnabled = true
let space = [SpaceServiceRoom].mockSingleRoom[0] let space = [SpaceServiceRoom].mockSingleRoom[0]
@@ -324,7 +324,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
}() }()
static let multipleAskToJoinSpacesMembersViewModel = { static let multipleAskToJoinSpacesMembersViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.knockingEnabled = true userSettings.knockingEnabled = true
let spaces = [SpaceServiceRoom].mockJoinedSpaces let spaces = [SpaceServiceRoom].mockJoinedSpaces
@@ -349,7 +349,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
isVisibleInPublicDirectory: true)), isVisibleInPublicDirectory: true)),
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userSettings: .volatile(), userSettings: .mock(),
appHooks: AppHooks()) appHooks: AppHooks())
static var previews: some View { static var previews: some View {
@@ -39,7 +39,7 @@ struct AnalyticsSettingsScreen: View {
struct AnalyticsSettingsScreen_Previews: PreviewProvider, TestablePreview { struct AnalyticsSettingsScreen_Previews: PreviewProvider, TestablePreview {
static var previews: some View { static var previews: some View {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let viewModel = AnalyticsSettingsScreenViewModel(userSettings: userSettings, let viewModel = AnalyticsSettingsScreenViewModel(userSettings: userSettings,
analytics: AnalyticsServiceMock(.init())) analytics: AnalyticsServiceMock(.init()))
AnalyticsSettingsScreen(context: viewModel.context) AnalyticsSettingsScreen(context: viewModel.context)
@@ -33,7 +33,7 @@ struct LegalInformationScreen: View {
// MARK: - Previews // MARK: - Previews
struct LegalInformationScreen_Previews: PreviewProvider, TestablePreview { struct LegalInformationScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = LegalInformationScreenViewModel(userSettings: .volatile()) static let viewModel = LegalInformationScreenViewModel(userSettings: .mock())
static var previews: some View { static var previews: some View {
LegalInformationScreen(context: viewModel.context) LegalInformationScreen(context: viewModel.context)
} }
@@ -262,7 +262,7 @@ struct NotificationSettingsScreen: View {
@available(iOS 26.0, *) @available(iOS 26.0, *)
struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview { struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel: NotificationSettingsScreenViewModel = { static let viewModel: NotificationSettingsScreenViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let notificationCenter = UserNotificationCenterMock() let notificationCenter = UserNotificationCenterMock()
notificationCenter.authorizationStatusReturnValue = .notDetermined notificationCenter.authorizationStatusReturnValue = .notDetermined
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
@@ -290,7 +290,7 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
}() }()
static let viewModelConfigurationMismatch: NotificationSettingsScreenViewModel = { static let viewModelConfigurationMismatch: NotificationSettingsScreenViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let notificationCenter = UserNotificationCenterMock() let notificationCenter = UserNotificationCenterMock()
notificationCenter.authorizationStatusReturnValue = .notDetermined notificationCenter.authorizationStatusReturnValue = .notDetermined
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
@@ -321,7 +321,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
deviceID: "AAAAAAAAAAA", deviceID: "AAAAAAAAAAA",
displayName: "Alice Liddell", displayName: "Alice Liddell",
status: .mockFocussing)))) status: .mockFocussing))))
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.multiAccountEnabled = true userSettings.multiAccountEnabled = true
return SettingsScreenViewModel(userSession: userSession, return SettingsScreenViewModel(userSession: userSession,
userSettings: userSettings, userSettings: userSettings,
@@ -145,7 +145,7 @@ struct UserDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
canChangeDisplayName: canChangeProfile)))) canChangeDisplayName: canChangeProfile))))
return UserDetailsEditScreenViewModel(userSession: userSession, return UserDetailsEditScreenViewModel(userSession: userSession,
mediaUploadingPreprocessor: .init(userSettings: .volatile()), mediaUploadingPreprocessor: .init(userSettings: .mock()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -132,7 +132,7 @@ struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview {
canonicalAlias: "#space:matrix.org", canonicalAlias: "#space:matrix.org",
members: members)), members: members)),
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -154,7 +154,7 @@ struct StartChatScreen: View {
struct StartChatScreen_Previews: PreviewProvider, TestablePreview { struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = { static let viewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com")))) let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
let userDiscoveryService = UserDiscoveryServiceMock() let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice]) userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
@@ -1306,7 +1306,7 @@ extension TimelineViewModel {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -340,7 +340,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
isViewSourceEnabled: true, isViewSourceEnabled: true,
areThreadsEnabled: true, areThreadsEnabled: true,
timelineKind: .live, timelineKind: .live,
emojiProvider: EmojiProvider(userSettings: .volatile())) emojiProvider: EmojiProvider(userSettings: .mock()))
guard let actions = provider.makeActions() else { return nil } guard let actions = provider.makeActions() else { return nil }
if var textItem = item as? TextRoomTimelineItem { if var textItem = item as? TextRoomTimelineItem {
@@ -52,7 +52,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}() }()
@@ -426,7 +426,7 @@ private extension TimelineItemKeyForwarder {
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview { struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
static let viewModel: TimelineViewModel = { static let viewModel: TimelineViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.threadsEnabled = true userSettings.threadsEnabled = true
let userSession = UserSessionMock(.init(userSettings: userSettings)) let userSession = UserSessionMock(.init(userSettings: userSettings))
@@ -445,7 +445,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
}() }()
static let viewModelWithPins: TimelineViewModel = { static let viewModelWithPins: TimelineViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.threadsEnabled = true userSettings.threadsEnabled = true
let userSession = UserSessionMock(.init(userSettings: userSettings)) 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 unsafeViewModel = TimelineViewModel.mock(contentScannerService: ContentScannerServiceMock(.init(scanResult: false)))
static let selectingViewModel: TimelineViewModel = { static let selectingViewModel: TimelineViewModel = {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.messageMultiSelectEnabled = true userSettings.messageMultiSelectEnabled = true
let userSession = UserSessionMock(.init(userSettings: userSettings)) let userSession = UserSessionMock(.init(userSettings: userSettings))
@@ -86,7 +86,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -97,7 +97,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -162,7 +162,7 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -232,11 +232,10 @@ class AuthenticationService: AuthenticationServiceProtocol {
let qrCodeHandler = client.newLoginWithQrCodeHandler(oauthConfiguration: appSettings.oAuthConfiguration.rustValue) let qrCodeHandler = client.newLoginWithQrCodeHandler(oauthConfiguration: appSettings.oAuthConfiguration.rustValue)
try await qrCodeHandler.scan(qrCodeData: qrData, progressListener: listener) try await qrCodeHandler.scan(qrCodeData: qrData, progressListener: listener)
// Since the QR code login flow includes verification.
appSettings.hasRunIdentityConfirmationOnboarding = true
switch await userSession(for: client) { switch await userSession(for: client) {
case .success(let userSession): case .success(let userSession):
// Since the QR code login flow includes verification.
userSession.userSettings.hasRunIdentityConfirmationOnboarding = true
progressSubject.send(.signedIn(userSession)) progressSubject.send(.signedIn(userSession))
case .failure(let error): case .failure(let error):
progressSubject.send(completion: .failure(error)) progressSubject.send(completion: .failure(error))
@@ -367,7 +366,7 @@ class AuthenticationService: AuthenticationServiceProtocol {
MXLog.info("Classic app account secrets imported.") MXLog.info("Classic app account secrets imported.")
// Importing the secrets automatically verifies the session. // Importing the secrets automatically verifies the session.
appSettings.hasRunIdentityConfirmationOnboarding = true appSettings.userSettings(for: classicAppAccount.userID).hasRunIdentityConfirmationOnboarding = true
} catch { } catch {
MXLog.error("Failed to import secrets for Classic app account: \(error)") MXLog.error("Failed to import secrets for Classic app account: \(error)")
} }
@@ -59,7 +59,7 @@ class UserSessionStore: UserSessionStoreProtocol {
return .failure(.missingCredentials) return .failure(.missingCredentials)
} }
let userSettings = UserSettings(appSettings: appSettings, accountSettings: .init()) let userSettings = appSettings.userSettings(for: credentials.userID)
switch await restorePreviousLogin(credentials, userSettings: userSettings) { switch await restorePreviousLogin(credentials, userSettings: userSettings) {
case .success(let clientProxy): case .success(let clientProxy):
@@ -83,7 +83,7 @@ class UserSessionStore: UserSessionStoreProtocol {
do { do {
let session = try client.session() let session = try client.session()
let userID = try client.userId() 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) let clientProxy = try await setupProxyForClient(client, userSettings: userSettings)
keychainController.setRestorationToken(RestorationToken(session: session, keychainController.setRestorationToken(RestorationToken(session: session,
@@ -298,7 +298,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)), roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)),
timelineController: TimelineControllerMock(.init()), timelineController: TimelineControllerMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -318,7 +318,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -338,7 +338,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -357,7 +357,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -382,7 +382,7 @@ class MockScreen: Identifiable {
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -407,7 +407,7 @@ class MockScreen: Identifiable {
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -431,7 +431,7 @@ class MockScreen: Identifiable {
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -457,7 +457,7 @@ class MockScreen: Identifiable {
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -482,7 +482,7 @@ class MockScreen: Identifiable {
roomProxy: roomProxy, roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -503,7 +503,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -537,7 +537,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -558,7 +558,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -579,7 +579,7 @@ class MockScreen: Identifiable {
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController, timelineController: timelineController,
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()), completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
@@ -597,14 +597,15 @@ class MockScreen: Identifiable {
requestDelay: .seconds(5)) requestDelay: .seconds(5))
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy, let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy,
flow: .deviceInitiator, flow: .deviceInitiator,
userSettings: .volatile(), userSettings: .mock(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
return SessionVerificationScreenCoordinator(parameters: parameters) return SessionVerificationScreenCoordinator(parameters: parameters)
case .userSessionScreen, .userSessionScreenReply, .userSessionSpacesFlow: case .userSessionScreen, .userSessionScreenReply, .userSessionSpacesFlow:
let appSettings: AppSettings = appSettings let userID = "@mock:client.com"
appSettings.hasRunIdentityConfirmationOnboarding = true let userSettings = appSettings.userSettings(for: userID)
appSettings.hasRunNotificationPermissionsOnboarding = true userSettings.hasRunIdentityConfirmationOnboarding = true
appSettings.analyticsConsentState = .optedOut userSettings.hasRunNotificationPermissionsOnboarding = true
userSettings.analyticsConsentState = .optedOut
let roomSummaries: [RoomSummary] = if id == .userSessionSpacesFlow { let roomSummaries: [RoomSummary] = if id == .userSessionSpacesFlow {
[[RoomSummary].mockSpaceInvites[0]] + .mockRooms [[RoomSummary].mockSpaceInvites[0]] + .mockRooms
@@ -612,7 +613,7 @@ class MockScreen: Identifiable {
.mockRooms .mockRooms
} }
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", let clientProxy = ClientProxyMock(.init(userID: userID,
deviceID: "MOCKCLIENT", deviceID: "MOCKCLIENT",
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))), roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))),
spaceServiceConfiguration: .init(topLevelSpaces: .mockSpaceList.filter(\.isSpace) + .mockSingleRoom), spaceServiceConfiguration: .init(topLevelSpaces: .mockSpaceList.filter(\.isSpace) + .mockSingleRoom),
@@ -634,8 +635,7 @@ class MockScreen: Identifiable {
let timelineControllerFactory = TimelineControllerFactoryMock(.init(timelineController: timelineController)) let timelineControllerFactory = TimelineControllerFactoryMock(.init(timelineController: timelineController))
let userSession = UserSessionMock(.init(clientProxy: clientProxy, let userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
userSettings: UserSettings(appSettings: appSettings, accountSettings: .init())))
let flowCoordinator = UserSessionFlowCoordinator(isNewLogin: false, let flowCoordinator = UserSessionFlowCoordinator(isNewLogin: false,
navigationRootCoordinator: navigationRootCoordinator, navigationRootCoordinator: navigationRootCoordinator,
appLockService: AppLockService(keychainController: KeychainControllerMock(), appLockService: AppLockService(keychainController: KeychainControllerMock(),
@@ -826,14 +826,15 @@ class MockScreen: Identifiable {
navigationRootCoordinator.setSheetCoordinator(navigationStackCoordinator) navigationRootCoordinator.setSheetCoordinator(navigationStackCoordinator)
return PlaceholderScreenCoordinator(hideBrandChrome: false) return PlaceholderScreenCoordinator(hideBrandChrome: false)
case .autoUpdatingTimeline: case .autoUpdatingTimeline:
let userSettings = UserSettings(appSettings: appSettings, accountSettings: .init()) let userID = "@mock:client.com"
appSettings.hasRunIdentityConfirmationOnboarding = true let userSettings = appSettings.userSettings(for: userID)
appSettings.hasRunNotificationPermissionsOnboarding = true userSettings.hasRunIdentityConfirmationOnboarding = true
appSettings.analyticsConsentState = .optedOut userSettings.hasRunNotificationPermissionsOnboarding = true
userSettings.analyticsConsentState = .optedOut
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: false)) let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: false))
navigationRootCoordinator.setRootCoordinator(navigationSplitCoordinator) 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 userSession = UserSessionMock(.init(clientProxy: clientProxy, userSettings: userSettings))
let roomProxy = JoinedRoomProxyMock(.init(id: "whatever", name: "okay", shouldUseAutoUpdatingTimeline: true)) let roomProxy = JoinedRoomProxyMock(.init(id: "whatever", name: "okay", shouldUseAutoUpdatingTimeline: true))
@@ -905,6 +906,6 @@ class MockScreen: Identifiable {
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")), stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userSettings: .volatile()) userSettings: .mock())
} }
} }
@@ -0,0 +1,93 @@
//
// 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.
//
@testable import ElementX
import Testing
struct AccountUserDefaultsTests {
private let store = VolatileUserDefaults()
private let aliceDefaults: AccountUserDefaults
private let bobDefaults: AccountUserDefaults
init() {
aliceDefaults = AccountUserDefaults(userID: "@alice:example.com", store: store)
bobDefaults = AccountUserDefaults(userID: "@bob:example.com", store: store)
}
@Test
func dictionaryRepresentation() {
// Given a store containing values for Alice, Bob and the app, all sharing a key.
aliceDefaults.set("one", forKey: "first")
aliceDefaults.set(2, forKey: "second")
bobDefaults.set("bob", forKey: "first")
store.set("global", forKey: "first")
#expect(aliceDefaults.object(forKey: "first") as? String == "one")
#expect(aliceDefaults.object(forKey: "second") as? Int == 2)
#expect(bobDefaults.object(forKey: "first") as? String == "bob")
#expect(store.object(forKey: "first") as? String == "global")
// When getting the dictionary representation of Alice's defaults.
let representation = aliceDefaults.dictionaryRepresentation()
// Then it should only contain Alice's values.
#expect(representation.count == 2)
#expect(representation["first"] as? String == "one")
#expect(representation["second"] as? Int == 2)
}
@Test
func reset() {
// Given a store containing values for Alice, Bob and the app, all sharing a key.
aliceDefaults.set("one", forKey: "first")
aliceDefaults.set(2, forKey: "second")
bobDefaults.set("bob", forKey: "first")
store.set("global", forKey: "first")
#expect(aliceDefaults.object(forKey: "first") as? String == "one")
#expect(aliceDefaults.object(forKey: "second") as? Int == 2)
#expect(bobDefaults.object(forKey: "first") as? String == "bob")
#expect(store.object(forKey: "first") as? String == "global")
// When resetting Alice's defaults.
aliceDefaults.reset()
// Then only Alice's values should be removed.
#expect(aliceDefaults.object(forKey: "first") == nil)
#expect(aliceDefaults.object(forKey: "second") == nil)
#expect(bobDefaults.object(forKey: "first") as? String == "bob")
#expect(store.object(forKey: "first") as? String == "global")
}
@Test
func migrateAppSettingsValue() {
// Given a store containing an app value.
store.set("global", forKey: "first")
#expect(store.object(forKey: "first") as? String == "global")
#expect(aliceDefaults.object(forKey: "first") == nil)
#expect(bobDefaults.object(forKey: "first") == nil)
// When migrating that value into Alice's defaults.
aliceDefaults.migrateAppSettingsValue(forKey: "first")
// Then the value should be moved to Alice's defaults only.
#expect(aliceDefaults.object(forKey: "first") as? String == "global")
#expect(store.object(forKey: "first") == nil)
#expect(bobDefaults.object(forKey: "first") == nil)
}
@Test
func migrateUnsetAppSettingsValue() {
// Given an empty store.
#expect(store.storage.isEmpty)
// When migrating a value that isn't set into Alice's defaults.
aliceDefaults.migrateAppSettingsValue(forKey: "first")
// Then nothing should be written to the store.
#expect(aliceDefaults.object(forKey: "first") == nil)
#expect(store.storage.isEmpty)
}
}
@@ -23,7 +23,7 @@ final class AnalyticsSettingsScreenViewModelTests {
client.isRunning = false client.isRunning = false
analytics = AnalyticsService(client: client, appSettings: appSettings) analytics = AnalyticsService(client: client, appSettings: appSettings)
viewModel = AnalyticsSettingsScreenViewModel(userSettings: UserSettings(appSettings: appSettings, accountSettings: .init()), viewModel = AnalyticsSettingsScreenViewModel(userSettings: appSettings.userSettings(for: "@me:matrix.org"),
analytics: analytics) analytics: analytics)
context = viewModel.context context = viewModel.context
} }
@@ -17,7 +17,7 @@ final class BugReportServiceTests {
var bugReportService: BugReportServiceProtocol! var bugReportService: BugReportServiceProtocol!
init() throws { init() throws {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
userSettings.bugReportRageshakeURL.reset() userSettings.bugReportRageshakeURL.reset()
let bugReportServiceMock = BugReportServiceMock() let bugReportServiceMock = BugReportServiceMock()
@@ -29,7 +29,7 @@ struct ChatsTabFlowCoordinatorTests {
} }
init() async throws { init() async throws {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
timelineControllerFactory = TimelineControllerFactoryMock(.init()) timelineControllerFactory = TimelineControllerFactoryMock(.init())
@@ -84,7 +84,7 @@ final class ComposerToolbarViewModelTests {
.init(suggestionType: .user(.init(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: nil)), range: .init(), rawSuggestionText: "")] .init(suggestionType: .user(.init(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: nil)), range: .init(), rawSuggestionText: "")]
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)) let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions))
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()), viewModel = ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
@@ -803,7 +803,7 @@ final class ComposerToolbarViewModelTests {
let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([]) let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([])
roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
@@ -846,7 +846,7 @@ final class ComposerToolbarViewModelTests {
roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
@@ -886,7 +886,7 @@ final class ComposerToolbarViewModelTests {
} }
roomProxyMock.identityStatusChangesPublisher = CurrentValueSubject([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinViolation)]).asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = CurrentValueSubject([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinViolation)]).asCurrentValuePublisher()
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
@@ -923,7 +923,7 @@ final class ComposerToolbarViewModelTests {
draftServiceMock.loadDraftClosure = loadDraftClosure draftServiceMock.loadDraftClosure = loadDraftClosure
} }
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = ComposerToolbarViewModel(initialText: initialText, viewModel = ComposerToolbarViewModel(initialText: initialText,
roomProxy: JoinedRoomProxyMock(.init()), roomProxy: JoinedRoomProxyMock(.init()),
@@ -24,7 +24,7 @@ final class CreateRoomScreenViewModelTests {
} }
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
} }
isolated deinit { isolated deinit {
@@ -55,7 +55,7 @@ struct EmojiPickerScreenViewModelTests {
emojiPickerStream = stream emojiPickerStream = stream
viewModel = EmojiPickerScreenViewModel(selectedEmojis: selectedEmojis, viewModel = EmojiPickerScreenViewModel(selectedEmojis: selectedEmojis,
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
continuation: continuation) continuation: continuation)
} }
} }
+4 -4
View File
@@ -19,7 +19,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = [category] emojiLoaderMock.categories = [category]
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .mock())
let categories = await emojiProvider.categories() let categories = await emojiProvider.categories()
#expect(emojiLoaderMock.categories == categories) #expect(emojiLoaderMock.categories == categories)
@@ -33,7 +33,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = [category] emojiLoaderMock.categories = [category]
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .mock())
let categories = await emojiProvider.categories(searchString: "") let categories = await emojiProvider.categories(searchString: "")
#expect(emojiLoaderMock.categories == categories) #expect(emojiLoaderMock.categories == categories)
@@ -51,7 +51,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = categoriesForFirstLoad emojiLoaderMock.categories = categoriesForFirstLoad
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .mock())
_ = await emojiProvider.categories() _ = await emojiProvider.categories()
emojiLoaderMock.categories = categoriesForSecondLoad emojiLoaderMock.categories = categoriesForSecondLoad
@@ -82,7 +82,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = categories emojiLoaderMock.categories = categories
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .mock())
_ = await emojiProvider.categories() _ = await emojiProvider.categories()
let result = await emojiProvider.categories(searchString: searchString) let result = await emojiProvider.categories(searchString: searchString)
@@ -25,7 +25,7 @@ final class HomeScreenViewModelTests {
var cancellables = Set<AnyCancellable>() var cancellables = Set<AnyCancellable>()
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
} }
@Test @Test
@@ -109,7 +109,7 @@ struct IdentityConfirmationScreenViewModelTests {
userSession.sessionSecurityStatePublisher = securityStateSubject.asCurrentValuePublisher() userSession.sessionSecurityStatePublisher = securityStateSubject.asCurrentValuePublisher()
viewModel = IdentityConfirmationScreenViewModel(userSession: userSession, viewModel = IdentityConfirmationScreenViewModel(userSession: userSession,
userSettings: .volatile(), userSettings: .mock(),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -34,7 +34,7 @@ final class JoinRoomScreenViewModelTests {
private let userSettings: UserSettings private let userSettings: UserSettings
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
} }
isolated deinit { isolated deinit {
@@ -228,7 +228,7 @@ final class LiveLocationManagerTests {
} }
private func setUp(accuracyAuthorization: CLAccuracyAuthorization = .fullAccuracy) { private func setUp(accuracyAuthorization: CLAccuracyAuthorization = .fullAccuracy) {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
clientProxy = ClientProxyMock(.init()) clientProxy = ClientProxyMock(.init())
beaconInfoSubject = PassthroughSubject<LiveLocationOwnInfoUpdate, Never>() beaconInfoSubject = PassthroughSubject<LiveLocationOwnInfoUpdate, Never>()
clientProxy.liveLocationOwnInfoUpdatesPublisher = beaconInfoSubject.eraseToAnyPublisher() clientProxy.liveLocationOwnInfoUpdatesPublisher = beaconInfoSubject.eraseToAnyPublisher()
@@ -417,7 +417,7 @@ struct LocationSharingScreenViewModelTests {
let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers)) let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers))
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil), viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil),
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
@@ -630,7 +630,7 @@ struct LocationSharingScreenViewModelTests {
private mutating func setupViewModel(liveLocationManagerMock: LiveLocationManagerMock, private mutating func setupViewModel(liveLocationManagerMock: LiveLocationManagerMock,
members: [RoomMemberProxyMock] = .allMembersAsAdmin) { members: [RoomMemberProxyMock] = .allMembersAsAdmin) {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
timelineProxy = TimelineProxyMock(.init()) timelineProxy = TimelineProxyMock(.init())
viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true), viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true),
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
@@ -649,7 +649,7 @@ struct LocationSharingScreenViewModelTests {
liveLocationsSubject: CurrentValueSubject<[LiveLocationShare], Never>, liveLocationsSubject: CurrentValueSubject<[LiveLocationShare], Never>,
members: [RoomMemberProxyMock] = .allMembers, members: [RoomMemberProxyMock] = .allMembers,
isSharingLiveLocationFromThisDevice: Bool = false) { isSharingLiveLocationFromThisDevice: Bool = false) {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
if isSharingLiveLocationFromThisDevice { if isSharingLiveLocationFromThisDevice {
userSettings.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture) userSettings.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture)
} }
@@ -28,7 +28,7 @@ final class MediaUploadPreviewScreenViewModelTests {
} }
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
userSettings.optimizeMediaUploads = false userSettings.optimizeMediaUploads = false
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
@@ -17,7 +17,7 @@ final class MediaUploadingPreprocessorTests {
var mediaUploadingPreprocessor: MediaUploadingPreprocessor! var mediaUploadingPreprocessor: MediaUploadingPreprocessor!
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
userSettings.optimizeMediaUploads = false userSettings.optimizeMediaUploads = false
mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings) mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings)
} }
@@ -23,7 +23,7 @@ struct NotificationSettingsScreenViewModelTests {
init() throws { init() throws {
userNotificationCenter = UserNotificationCenterMock() userNotificationCenter = UserNotificationCenterMock()
userNotificationCenter.authorizationStatusReturnValue = .authorized userNotificationCenter.authorizationStatusReturnValue = .authorized
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
notificationSettingsProxy = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxy = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .allMessages notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .allMessages
notificationSettingsProxy.isRoomMentionEnabledReturnValue = true notificationSettingsProxy.isRoomMentionEnabledReturnValue = true
@@ -18,7 +18,7 @@ struct NotificationToneManagerTests {
private let manager: NotificationToneManager private let manager: NotificationToneManager
init() { init() {
manager = NotificationToneManager(userSettings: .volatile()) manager = NotificationToneManager(userSettings: .mock())
} }
// MARK: - Deletion // MARK: - Deletion
+11 -11
View File
@@ -28,7 +28,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
@@ -60,7 +60,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
@@ -84,7 +84,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
@@ -108,7 +108,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body)))
@@ -131,7 +131,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body)))
@@ -158,7 +158,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body)))
@@ -181,7 +181,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body)))
@@ -206,7 +206,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body)))
@@ -229,7 +229,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body)))
@@ -256,7 +256,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body)))
@@ -279,7 +279,7 @@ struct PillContextTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body)))
+1 -1
View File
@@ -21,7 +21,7 @@ struct PresenceServiceTests {
init() { init() {
clientProxy = ClientProxyMock(.init()) clientProxy = ClientProxyMock(.init())
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
notificationCenter = NotificationCenter() notificationCenter = NotificationCenter()
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in
@@ -167,7 +167,7 @@ struct RoomDetailsEditScreenViewModelTests {
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
viewModel = .init(roomProxy: JoinedRoomProxyMock(roomProxyConfiguration), viewModel = .init(roomProxy: JoinedRoomProxyMock(roomProxyConfiguration),
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
userIndicatorController: userIndicatorController) userIndicatorController: userIndicatorController)
} }
} }
@@ -30,7 +30,7 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -44,7 +44,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -65,7 +65,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -87,7 +87,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -146,7 +146,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -168,7 +168,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -201,7 +201,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -233,7 +233,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -266,7 +266,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -300,7 +300,7 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -318,7 +318,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -367,7 +367,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -403,7 +403,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -439,7 +439,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -460,7 +460,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -481,7 +481,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -500,7 +500,7 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error") notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error")
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -709,7 +709,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -731,7 +731,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -755,7 +755,7 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -779,7 +779,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -807,7 +807,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
userSettings: UserSettings.volatile(), userSettings: UserSettings.mock(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -22,7 +22,7 @@ final class RoomFlowCoordinatorTests {
private let userSettings: UserSettings private let userSettings: UserSettings
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
} }
@Test @Test
@@ -17,7 +17,7 @@ final class RoomListFiltersStateTests {
let defaultFilters = RoomListFilter.allCases.filter { $0 != .mentions && $0 != .lowPriority } let defaultFilters = RoomListFilter.allCases.filter { $0 != .mentions && $0 != .lowPriority }
init() { init() {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
state = RoomListFiltersState(userSettings: userSettings) state = RoomListFiltersState(userSettings: userSettings)
} }
@@ -51,7 +51,7 @@ struct RoomMembersFlowCoordinatorTests {
let clientProxy = ClientProxyMock(.init()) let clientProxy = ClientProxyMock(.init())
clientProxy.directRoomForUserIDReturnValue = .success(nil) clientProxy.directRoomForUserIDReturnValue = .success(nil)
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
@@ -153,7 +153,7 @@ final class RoomScreenViewModelTests {
@Test @Test
func pinnedEventsBannerThreadedSelection() async throws { func pinnedEventsBannerThreadedSelection() async throws {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.threadsEnabled = true userSettings.threadsEnabled = true
let userSession = UserSessionMock(.init(userSettings: userSettings)) let userSession = UserSessionMock(.init(userSettings: userSettings))
@@ -122,7 +122,7 @@ final class RoomSummaryProviderTests {
// MARK: - Helpers // MARK: - Helpers
private func setup(isLowPriorityFilterEnabled: Bool = false, includesOnlyJoinedRooms: Bool = false, setsRoomList: Bool = true) { private func setup(isLowPriorityFilterEnabled: Bool = false, includesOnlyJoinedRooms: Bool = false, setsRoomList: Bool = true) {
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
userSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled userSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled
let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org") let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org")
@@ -54,7 +54,7 @@ struct SearchScreenViewModelTests {
staticRoomListSubject.value.first { $0.id == identifier } staticRoomListSubject.value.first { $0.id == identifier }
} }
userSettings = UserSettings.volatile() userSettings = UserSettings.mock()
viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
clientProxy: clientProxy, clientProxy: clientProxy,
@@ -457,7 +457,7 @@ final class SecurityAndPrivacyScreenViewModelTests {
topLevelSpaces: [SpaceServiceRoom] = [], topLevelSpaces: [SpaceServiceRoom] = [],
joinRule: ElementX.JoinRule, joinRule: ElementX.JoinRule,
forceDisableE2EE: Bool = false) { forceDisableE2EE: Bool = false) {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.knockingEnabled = true userSettings.knockingEnabled = true
userSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE) userSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE)
roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false, roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false,
@@ -21,7 +21,7 @@ struct SessionVerificationViewModelTests {
sessionVerificationController = SessionVerificationControllerProxyMock.configureMock() sessionVerificationController = SessionVerificationControllerProxyMock.configureMock()
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController, viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController,
flow: .deviceInitiator, flow: .deviceInitiator,
userSettings: .volatile(), userSettings: .mock(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
context = viewModel.context context = viewModel.context
} }
@@ -176,7 +176,7 @@ struct SettingsScreenViewModelTests {
@Test @Test
mutating func addAccountButtonFollowsTheFeatureFlag() async throws { mutating func addAccountButtonFollowsTheFeatureFlag() async throws {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
setupViewModel(userSettings: userSettings) setupViewModel(userSettings: userSettings)
#expect(!context.viewState.showAddAccountButton) #expect(!context.viewState.showAddAccountButton)
@@ -200,7 +200,7 @@ struct SettingsScreenViewModelTests {
// MARK: - Helpers // MARK: - Helpers
private mutating func setupViewModel(status: UserStatus = .init(), userSettings: UserSettings = .volatile()) { private mutating func setupViewModel(status: UserStatus = .init(), userSettings: UserSettings = .mock()) {
clientProxy = ClientProxyMock(.init(userID: "", status: status)) clientProxy = ClientProxyMock(.init(userID: "", status: status))
viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)), viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userSettings: userSettings, userSettings: userSettings,
@@ -55,7 +55,7 @@ struct TimelineControllerTests {
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")), stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")),
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userSettings: .volatile()) userSettings: .mock())
} }
/// The live timeline's items are only published once any initial focus attempt has finished. /// The live timeline's items are only published once any initial focus attempt has finished.
@@ -218,7 +218,7 @@ struct TimelineInteractionHandlerTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -123,7 +123,7 @@ struct TimelineItemMenuActionProviderTests {
isViewSourceEnabled: true, isViewSourceEnabled: true,
areThreadsEnabled: true, areThreadsEnabled: true,
timelineKind: timelineKind, timelineKind: timelineKind,
emojiProvider: EmojiProvider(userSettings: .volatile())) emojiProvider: EmojiProvider(userSettings: .mock()))
.makeActions() .makeActions()
} }
} }
+11 -11
View File
@@ -301,7 +301,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
return (viewModel, roomProxy, timelineProxy, timelineController) return (viewModel, roomProxy, timelineProxy, timelineController)
@@ -326,7 +326,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -350,7 +350,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -386,7 +386,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -422,7 +422,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -464,7 +464,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
#expect(configuration.pinnedEventIDs == viewModel.context.viewState.pinnedEventIDs) #expect(configuration.pinnedEventIDs == viewModel.context.viewState.pinnedEventIDs)
@@ -492,7 +492,7 @@ final class TimelineViewModelTests {
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -899,7 +899,7 @@ final class TimelineViewModelTests {
@Test @Test
func disablingTheFlagClearsTheSelection() async throws { func disablingTheFlagClearsTheSelection() async throws {
let items = [TextRoomTimelineItem(eventID: "$1")] let items = [TextRoomTimelineItem(eventID: "$1")]
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.messageMultiSelectEnabled = true userSettings.messageMultiSelectEnabled = true
let viewModel = makeViewModel(timelineController: TimelineControllerMock(.init(timelineItems: items)), userSettings: userSettings) let viewModel = makeViewModel(timelineController: TimelineControllerMock(.init(timelineItems: items)), userSettings: userSettings)
@@ -917,7 +917,7 @@ final class TimelineViewModelTests {
focussedEventID: String? = nil, focussedEventID: String? = nil,
timelineController: TimelineControllerProtocol, timelineController: TimelineControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock(),
userSettings: UserSettings = .volatile()) -> TimelineViewModel { userSettings: UserSettings = .mock()) -> TimelineViewModel {
TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")), TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")),
focussedEventID: focussedEventID, focussedEventID: focussedEventID,
timelineController: timelineController, timelineController: timelineController,
@@ -926,7 +926,7 @@ final class TimelineViewModelTests {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(userSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .mock()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -944,7 +944,7 @@ final class TimelineViewModelTests {
private func makeSelectionViewModel(timelineController: TimelineControllerProtocol, private func makeSelectionViewModel(timelineController: TimelineControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock()) -> TimelineViewModel { userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock()) -> TimelineViewModel {
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
userSettings.messageMultiSelectEnabled = true userSettings.messageMultiSelectEnabled = true
return makeViewModel(timelineController: timelineController, return makeViewModel(timelineController: timelineController,
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
@@ -20,7 +20,7 @@ struct UserDetailsEditScreenViewModelTests {
init() { init() {
viewModel = .init(userSession: UserSessionMock(.init()), viewModel = .init(userSession: UserSessionMock(.init()),
mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .mock()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
@@ -48,7 +48,7 @@ struct UserSessionFlowCoordinatorTests {
appMediator.networkMonitor = networkMonitor appMediator.networkMonitor = networkMonitor
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
let userSettings = UserSettings.volatile() let userSettings = UserSettings.mock()
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
+102
View File
@@ -0,0 +1,102 @@
//
// 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.
//
@testable import ElementX
import Foundation
import Testing
struct UserSettingsTests {
private let store = VolatileUserDefaults()
private let appSettings: AppSettings
private let aliceSettings: UserSettings
private let bobSettings: UserSettings
init() {
appSettings = AppSettings(store: store)
aliceSettings = appSettings.userSettings(for: "@alice:example.com")
bobSettings = appSettings.userSettings(for: "@bob:example.com")
}
@Test
func accountSettingsAreScopedToAccount() {
// Given settings for two different accounts.
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
#expect(bobSettings.searchBreadcrumbs.isEmpty)
// When updating an account setting for Alice.
aliceSettings.searchBreadcrumbs = [.query("Alice")]
// Then only Alice should see the change.
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
#expect(bobSettings.searchBreadcrumbs.isEmpty)
}
@Test
func appSettingsAreShared() {
// Given settings for two different accounts.
#expect(!appSettings.hasSignedInBefore)
#expect(!aliceSettings.hasSignedInBefore)
#expect(!bobSettings.hasSignedInBefore)
// When updating an app setting through Alice's settings.
aliceSettings.hasSignedInBefore = true
// Then the change should be seen by the app and every account.
#expect(appSettings.hasSignedInBefore)
#expect(aliceSettings.hasSignedInBefore)
#expect(bobSettings.hasSignedInBefore)
}
@Test
func migrateAppSettingsValueToAccountSettings() throws {
// Given a store containing values saved under the keys previously used by the app settings.
// These keys are hardcoded so that renaming a property breaks this test instead of the migration.
store.set(true, forKey: "hasRunIdentityConfirmationOnboarding")
try store.set(JSONEncoder().encode([SearchBreadcrumb.query("Alice")]), forKey: "searchBreadcrumbs")
#expect(store.object(forKey: "hasRunIdentityConfirmationOnboarding") != nil)
#expect(store.object(forKey: "searchBreadcrumbs") != nil)
#expect(!aliceSettings.hasRunIdentityConfirmationOnboarding)
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
// When migrating those values into Alice's account settings.
aliceSettings.migrateAppSettingsValueToAccountSettings(\.hasRunIdentityConfirmationOnboardingKey)
aliceSettings.migrateAppSettingsValueToAccountSettings(\.searchBreadcrumbsKey)
// Then the values should belong to Alice only.
#expect(aliceSettings.hasRunIdentityConfirmationOnboarding)
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
#expect(!bobSettings.hasRunIdentityConfirmationOnboarding)
#expect(bobSettings.searchBreadcrumbs.isEmpty)
#expect(store.object(forKey: "hasRunIdentityConfirmationOnboarding") == nil)
#expect(store.object(forKey: "searchBreadcrumbs") == nil)
}
@Test
func resetSessionSpecificSettings() {
// Given app settings and account settings for two different accounts.
appSettings.hasSignedInBefore = true
aliceSettings.hasRunIdentityConfirmationOnboarding = true
aliceSettings.searchBreadcrumbs = [.query("Alice")]
bobSettings.hasRunIdentityConfirmationOnboarding = true
bobSettings.searchBreadcrumbs = [.query("Bob")]
#expect(appSettings.hasSignedInBefore)
#expect(aliceSettings.hasRunIdentityConfirmationOnboarding)
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
#expect(bobSettings.hasRunIdentityConfirmationOnboarding)
#expect(bobSettings.searchBreadcrumbs == [.query("Bob")])
// When resetting Alice's session specific settings.
aliceSettings.resetSessionSpecificSettings()
// Then only Alice's account settings should be reset.
#expect(!aliceSettings.hasRunIdentityConfirmationOnboarding)
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
#expect(bobSettings.hasRunIdentityConfirmationOnboarding)
#expect(bobSettings.searchBreadcrumbs == [.query("Bob")])
#expect(appSettings.hasSignedInBefore)
}
}
+1 -1
View File
@@ -51,7 +51,7 @@ settings:
ENABLE_BITCODE: false ENABLE_BITCODE: false
APP_NAME: ElementX APP_NAME: ElementX
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)" KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(DEVELOPMENT_TEAM).$(BASE_BUNDLE_IDENTIFIER)"
MARKETING_VERSION: 26.10.0 MARKETING_VERSION: 26.10.1
CURRENT_PROJECT_VERSION: 1 CURRENT_PROJECT_VERSION: 1
SUPPORTS_MACCATALYST: false SUPPORTS_MACCATALYST: false
ARCHS: arm64 ARCHS: arm64