Crypto identity reset (#3107)

* Add EncryptionReset password entry screen

* Expose client proxy identity reset method

* Update the IdentityConfirmationScreen to the latest designs

* Replace the old recovery key reset screen with a new EncryptionReset one

* Fixes #3102 - Add support for resetting the user's whole crypto identity

* Address review comments

* Bump the SDK to v1.0.30
This commit is contained in:
Stefan Ceriu
2024-08-05 09:35:18 +03:00
committed by GitHub
parent 276bbb09f2
commit 63e0b94764
58 changed files with 1217 additions and 319 deletions
+81 -37
View File
@@ -65,6 +65,7 @@
0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */; }; 0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */; };
0C47AE2CA7929CB3B0E2D793 /* ServerSelectionScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */; }; 0C47AE2CA7929CB3B0E2D793 /* ServerSelectionScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */; };
0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */; }; 0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */; };
0C6DF318E9C8F6461E6ABDE7 /* EncryptionResetPasswordScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */; };
0C797CD650DFD2876BEC5173 /* CollapsibleReactionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */; }; 0C797CD650DFD2876BEC5173 /* CollapsibleReactionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */; };
0C88044649BAEE6C49BFC43A /* SecureBackupControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */; }; 0C88044649BAEE6C49BFC43A /* SecureBackupControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */; };
0C932A5158C1D0604DFC5750 /* ComposerToolbarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */; }; 0C932A5158C1D0604DFC5750 /* ComposerToolbarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */; };
@@ -203,6 +204,7 @@
2F66701B15657A87B4AC3A0A /* WaitlistScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */; }; 2F66701B15657A87B4AC3A0A /* WaitlistScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */; };
2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; }; 2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; };
2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */; }; 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */; };
3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */; };
3042527CB344A9EF1157FC26 /* AudioRecorderStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */; }; 3042527CB344A9EF1157FC26 /* AudioRecorderStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */; };
308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; }; 308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; };
30CC1DB7CE357659C82AA115 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; }; 30CC1DB7CE357659C82AA115 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; };
@@ -227,6 +229,7 @@
35E975CFDA60E05362A7CF79 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1222DB76B917EB8A55365BA5 /* target.yml */; }; 35E975CFDA60E05362A7CF79 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1222DB76B917EB8A55365BA5 /* target.yml */; };
366D5BFE52CB79E804C7D095 /* CallScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */; }; 366D5BFE52CB79E804C7D095 /* CallScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */; };
368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */; }; 368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */; };
36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */; };
369BF960E52BBEE61F8A5BD1 /* BlockedUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */; }; 369BF960E52BBEE61F8A5BD1 /* BlockedUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */; };
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; };
36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 75361A9D8A3C5501EADB225D /* SentrySwiftUI */; }; 36AD4DD4C798E22584ED3200 /* SentrySwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 75361A9D8A3C5501EADB225D /* SentrySwiftUI */; };
@@ -257,7 +260,6 @@
3C549A0BF39F8A854D45D9FD /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; }; 3C549A0BF39F8A854D45D9FD /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */; }; 3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */; };
3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62B07B296D7A9D2F09120853 /* OrderedSet.swift */; }; 3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62B07B296D7A9D2F09120853 /* OrderedSet.swift */; };
3D2E3E1B01D4389DCBE8F0E8 /* ResetRecoveryKeyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E995E3F726488F8938F0BCD1 /* ResetRecoveryKeyScreenCoordinator.swift */; };
3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; }; 3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; };
3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */; }; 3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */; };
3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */; }; 3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */; };
@@ -439,7 +441,6 @@
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; }; 67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; };
67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */; }; 67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */; };
680062C402ECB8FCAAE85A5C /* ResetRecoveryKeyScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99637028A8BD2843A35A92D4 /* ResetRecoveryKeyScreenViewModelProtocol.swift */; };
6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */; }; 6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */; };
68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; }; 68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; };
6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; }; 6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
@@ -654,6 +655,7 @@
97189E495F0E47805D1868DB /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 527578916BD388A09F5A8036 /* DTCoreText */; }; 97189E495F0E47805D1868DB /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 527578916BD388A09F5A8036 /* DTCoreText */; };
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; }; 978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
97969EF0B9C412CD38E5CA93 /* AppLockScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */; }; 97969EF0B9C412CD38E5CA93 /* AppLockScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */; };
97BAEDD9054FB5F233EE928B /* EncryptionResetScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */; };
981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */; }; 981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */; };
983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */; }; 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */; };
9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */; }; 9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */; };
@@ -674,7 +676,6 @@
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; }; 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; }; 9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; };
9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; }; 9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; };
9C9838B68C00C980A498050C /* ResetRecoveryKeyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC30DEC0097B9D217493007 /* ResetRecoveryKeyScreen.swift */; };
9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; }; 9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; };
9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; }; 9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; };
9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C75EF87651B00A176AB08E97 /* AppDelegate.swift */; }; 9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C75EF87651B00A176AB08E97 /* AppDelegate.swift */; };
@@ -690,6 +691,8 @@
9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */; }; 9FB41B0E8B2AA9B404E52C8B /* AppLockSetupBiometricsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */; };
A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */; }; A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */; };
A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */; }; A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */; };
A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */; };
A0868BDE84D2140A885BE3C9 /* EncryptionResetScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */; };
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; }; A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; }; A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; };
A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */; }; A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */; };
@@ -765,6 +768,7 @@
B1387648C6F71F1B98244803 /* SecureBackupRecoveryKeyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */; }; B1387648C6F71F1B98244803 /* SecureBackupRecoveryKeyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */; };
B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; };
B188D0907A4D38AAAF6FEFA8 /* AppLockSetupFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */; }; B188D0907A4D38AAAF6FEFA8 /* AppLockSetupFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */; };
B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */; };
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; }; B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; };
B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; }; B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; };
B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */; }; B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */; };
@@ -926,6 +930,7 @@
D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; };
D5EA4C6C80579279770D5804 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */; }; D5EA4C6C80579279770D5804 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */; };
D5FE90A6AF5FD5AE91BD37C7 /* NotificationSettingsEditScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */; }; D5FE90A6AF5FD5AE91BD37C7 /* NotificationSettingsEditScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */; };
D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */; };
D63974A88CF2BC721F109C77 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = DCA3C4A997AD28E6918D4CE5 /* Compound */; }; D63974A88CF2BC721F109C77 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = DCA3C4A997AD28E6918D4CE5 /* Compound */; };
D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */; }; D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */; };
D6DE764B17FB4A9A12C33BF4 /* MessageComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */; }; D6DE764B17FB4A9A12C33BF4 /* MessageComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */; };
@@ -954,7 +959,6 @@
DFCA89C4EC2A5332ED6B441F /* DataProtectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4959CECEC984B3995616F427 /* DataProtectionManager.swift */; }; DFCA89C4EC2A5332ED6B441F /* DataProtectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4959CECEC984B3995616F427 /* DataProtectionManager.swift */; };
DFD5AA8688A34C72D48AF3B1 /* StaticLocationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */; }; DFD5AA8688A34C72D48AF3B1 /* StaticLocationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */; };
DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; }; DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; };
E07ABB9FD1C87EBBDDE81DC5 /* ResetRecoveryKeyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63616A8920EC6948B31EA1B /* ResetRecoveryKeyScreenViewModel.swift */; };
E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */; }; E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E625B0EB2F86B37C14EF7E6 /* SettingsScreenViewModel.swift */; };
E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */; }; E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */; };
E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; }; E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; };
@@ -1011,7 +1015,7 @@
EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */; }; EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */; };
EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; };
EC65AF0D9240A248DC9917BB /* ResetRecoveryKeyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76911C322BC4CD117A8A0AF1 /* ResetRecoveryKeyScreenModels.swift */; }; EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */; };
ECA636DAF071C611FDC2BB57 /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; ECA636DAF071C611FDC2BB57 /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
ED564C8C7C43CF5F67000368 /* PlatformViewVersionPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */; }; ED564C8C7C43CF5F67000368 /* PlatformViewVersionPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */; };
ED90A59F068FD0CA27E602ED /* UserProfileListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */; }; ED90A59F068FD0CA27E602ED /* UserProfileListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */; };
@@ -1043,6 +1047,7 @@
F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */; }; F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */; };
F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */; }; F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */; };
F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; }; F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; };
F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */; };
F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; }; F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; };
F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; }; F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; };
F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; }; F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; };
@@ -1360,7 +1365,9 @@
2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelTests.swift; sourceTree = "<group>"; }; 2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelTests.swift; sourceTree = "<group>"; };
2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsViewModelTests.swift; sourceTree = "<group>"; }; 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsViewModelTests.swift; sourceTree = "<group>"; };
2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = "<group>"; }; 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = "<group>"; };
303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModel.swift; sourceTree = "<group>"; };
303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = "<group>"; }; 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = "<group>"; };
306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenModels.swift; sourceTree = "<group>"; };
307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreen.swift; sourceTree = "<group>"; }; 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreen.swift; sourceTree = "<group>"; };
309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = "<group>"; }; 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = "<group>"; };
30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = "<group>"; }; 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = "<group>"; };
@@ -1477,6 +1484,7 @@
49E45C3DC740D3AB9A47FD32 /* SwipeToReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToReplyView.swift; sourceTree = "<group>"; }; 49E45C3DC740D3AB9A47FD32 /* SwipeToReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToReplyView.swift; sourceTree = "<group>"; };
49E6066092ED45E36BB306F7 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.stringsdict"; sourceTree = "<group>"; }; 49E6066092ED45E36BB306F7 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationRequest.swift; sourceTree = "<group>"; }; 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationRequest.swift; sourceTree = "<group>"; };
4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModelProtocol.swift; sourceTree = "<group>"; };
4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimerTests.swift; sourceTree = "<group>"; }; 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimerTests.swift; sourceTree = "<group>"; };
4AB7D7DAAAF662DED9D02379 /* MockMediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaLoader.swift; sourceTree = "<group>"; }; 4AB7D7DAAAF662DED9D02379 /* MockMediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaLoader.swift; sourceTree = "<group>"; };
4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = "<group>"; }; 4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = "<group>"; };
@@ -1518,6 +1526,7 @@
542D4F49FABA056DEEEB3400 /* RustTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustTracing.swift; sourceTree = "<group>"; }; 542D4F49FABA056DEEEB3400 /* RustTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustTracing.swift; sourceTree = "<group>"; };
5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = "<group>"; }; 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = "<group>"; };
5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = "<group>"; }; 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = "<group>"; };
54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = "<group>"; };
54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = "<group>"; }; 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = "<group>"; };
5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSoftLogoutScreenState.swift; sourceTree = "<group>"; }; 5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSoftLogoutScreenState.swift; sourceTree = "<group>"; };
@@ -1530,6 +1539,7 @@
57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLocator.swift; sourceTree = "<group>"; }; 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLocator.swift; sourceTree = "<group>"; };
584509A363ADF6244DFDB96A /* CallNotificationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallNotificationRoomTimelineView.swift; sourceTree = "<group>"; }; 584509A363ADF6244DFDB96A /* CallNotificationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallNotificationRoomTimelineView.swift; sourceTree = "<group>"; };
584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; }; 584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; };
5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModel.swift; sourceTree = "<group>"; };
58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelTests.swift; sourceTree = "<group>"; }; 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; }; 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; }; 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; };
@@ -1599,7 +1609,6 @@
6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsScreenIdentifier.swift; sourceTree = "<group>"; }; 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsScreenIdentifier.swift; sourceTree = "<group>"; };
6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelTests.swift; sourceTree = "<group>"; }; 6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelTests.swift; sourceTree = "<group>"; };
6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationUITests.swift; sourceTree = "<group>"; }; 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationUITests.swift; sourceTree = "<group>"; };
6DC30DEC0097B9D217493007 /* ResetRecoveryKeyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreen.swift; sourceTree = "<group>"; };
6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatViewModelTests.swift; sourceTree = "<group>"; }; 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatViewModelTests.swift; sourceTree = "<group>"; };
6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; }; 6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; };
6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelTests.swift; sourceTree = "<group>"; }; 6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelTests.swift; sourceTree = "<group>"; };
@@ -1636,7 +1645,6 @@
7509AB72755DCC4B4E721B36 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SAS.strings; sourceTree = "<group>"; }; 7509AB72755DCC4B4E721B36 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SAS.strings; sourceTree = "<group>"; };
752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signposter.swift; sourceTree = "<group>"; }; 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signposter.swift; sourceTree = "<group>"; };
76310030C831D4610A705603 /* URLComponentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsTests.swift; sourceTree = "<group>"; }; 76310030C831D4610A705603 /* URLComponentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsTests.swift; sourceTree = "<group>"; };
76911C322BC4CD117A8A0AF1 /* ResetRecoveryKeyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreenModels.swift; sourceTree = "<group>"; };
772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; }; 772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
7773CBFDBD458E0B7E270507 /* PillView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillView.swift; sourceTree = "<group>"; }; 7773CBFDBD458E0B7E270507 /* PillView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillView.swift; sourceTree = "<group>"; };
780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModel.swift; sourceTree = "<group>"; }; 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModel.swift; sourceTree = "<group>"; };
@@ -1669,6 +1677,7 @@
7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenCoordinator.swift; sourceTree = "<group>"; }; 7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModelProtocol.swift; sourceTree = "<group>"; };
7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInviterLabel.swift; sourceTree = "<group>"; }; 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInviterLabel.swift; sourceTree = "<group>"; };
7EC2F1622C5BBABED6012E12 /* HeroImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroImage.swift; sourceTree = "<group>"; }; 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroImage.swift; sourceTree = "<group>"; };
7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelTests.swift; sourceTree = "<group>"; }; 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelTests.swift; sourceTree = "<group>"; };
@@ -1677,6 +1686,7 @@
7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = "<group>"; }; 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = "<group>"; };
80C4927D09099497233E9980 /* WaitlistScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreen.swift; sourceTree = "<group>"; }; 80C4927D09099497233E9980 /* WaitlistScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreen.swift; sourceTree = "<group>"; };
80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageEventStringBuilder.swift; sourceTree = "<group>"; }; 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageEventStringBuilder.swift; sourceTree = "<group>"; };
811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreen.swift; sourceTree = "<group>"; };
8140010A796DB2C7977B6643 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; }; 8140010A796DB2C7977B6643 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
8166F121C79C7B62BF01D508 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pt; path = pt.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 8166F121C79C7B62BF01D508 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pt; path = pt.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = "<group>"; }; 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -1734,6 +1744,7 @@
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; };
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; }; 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; };
8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = "<group>"; };
8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = "<group>"; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = "<group>"; };
8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = "<group>"; }; 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = "<group>"; };
8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = "<group>"; }; 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = "<group>"; };
@@ -1772,7 +1783,6 @@
989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelTests.swift; sourceTree = "<group>"; }; 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelTests.swift; sourceTree = "<group>"; };
989FC684408B31A677F5538B /* CompletionSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionView.swift; sourceTree = "<group>"; }; 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionView.swift; sourceTree = "<group>"; };
98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; }; 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; };
99637028A8BD2843A35A92D4 /* ResetRecoveryKeyScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreenViewModelProtocol.swift; sourceTree = "<group>"; };
997BF045585AF6DB2EBC5755 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 997BF045585AF6DB2EBC5755 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinator.swift; sourceTree = "<group>"; }; 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinator.swift; sourceTree = "<group>"; };
9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeLabel.swift; sourceTree = "<group>"; }; 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeLabel.swift; sourceTree = "<group>"; };
@@ -1967,7 +1977,6 @@
C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreen.swift; sourceTree = "<group>"; }; C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreen.swift; sourceTree = "<group>"; };
C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModelProtocol.swift; sourceTree = "<group>"; }; C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinator.swift; sourceTree = "<group>"; }; C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinator.swift; sourceTree = "<group>"; };
C63616A8920EC6948B31EA1B /* ResetRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreenViewModel.swift; sourceTree = "<group>"; };
C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = "<group>"; }; C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = "<group>"; };
C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; }; C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; }; C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; };
@@ -2075,6 +2084,7 @@
E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterModels.swift; sourceTree = "<group>"; }; E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterModels.swift; sourceTree = "<group>"; };
E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = "<group>"; }; E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = "<group>"; };
E0FCA0957FAA0E15A9F5579D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Untranslated.stringsdict; sourceTree = "<group>"; }; E0FCA0957FAA0E15A9F5579D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Untranslated.stringsdict; sourceTree = "<group>"; };
E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenCoordinator.swift; sourceTree = "<group>"; };
E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileListRow.swift; sourceTree = "<group>"; }; E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileListRow.swift; sourceTree = "<group>"; };
E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenCoordinator.swift; sourceTree = "<group>"; }; E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenCoordinator.swift; sourceTree = "<group>"; };
E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreen.swift; sourceTree = "<group>"; }; E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreen.swift; sourceTree = "<group>"; };
@@ -2103,6 +2113,7 @@
E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersView.swift; sourceTree = "<group>"; }; E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersView.swift; sourceTree = "<group>"; };
E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = secrets.xcconfig; sourceTree = "<group>"; }; E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = secrets.xcconfig; sourceTree = "<group>"; };
E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedItemsIndicatorView.swift; sourceTree = "<group>"; }; E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedItemsIndicatorView.swift; sourceTree = "<group>"; };
E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenCoordinator.swift; sourceTree = "<group>"; };
E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; }; E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; };
E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = "<group>"; }; E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = "<group>"; };
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = "<group>"; }; E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
@@ -2116,7 +2127,6 @@
E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; }; E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; };
E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = "<group>"; }; E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.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>"; };
E995E3F726488F8938F0BCD1 /* ResetRecoveryKeyScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreenCoordinator.swift; sourceTree = "<group>"; };
E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInviteRoomTimelineItem.swift; sourceTree = "<group>"; }; E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInviteRoomTimelineItem.swift; sourceTree = "<group>"; };
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelTests.swift; sourceTree = "<group>"; }; EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelTests.swift; sourceTree = "<group>"; };
@@ -2322,14 +2332,6 @@
path = VoiceMessage; path = VoiceMessage;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
01DF58ADE41080A419AD424A /* View */ = {
isa = PBXGroup;
children = (
6DC30DEC0097B9D217493007 /* ResetRecoveryKeyScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */ = { 0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -2601,7 +2603,6 @@
2565414373E6F68005966B8E /* SecureBackup */ = { 2565414373E6F68005966B8E /* SecureBackup */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EE703B39AC7A2862CFDCA12C /* ResetKeyScreen */,
B1FD4FD6CEB987AE274AEEE5 /* SecureBackupKeyBackupScreen */, B1FD4FD6CEB987AE274AEEE5 /* SecureBackupKeyBackupScreen */,
63E514D74481A3D9556DFFC3 /* SecureBackupLogoutConfirmationScreen */, 63E514D74481A3D9556DFFC3 /* SecureBackupLogoutConfirmationScreen */,
6E8F16377AD462BBD4951271 /* SecureBackupRecoveryKeyScreen */, 6E8F16377AD462BBD4951271 /* SecureBackupRecoveryKeyScreen */,
@@ -3143,6 +3144,14 @@
path = Polls; path = Polls;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
459B661EA3598F9E709E81A7 /* View */ = {
isa = PBXGroup;
children = (
8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
464C6BFAA853DC755B9C1F60 /* PinnedItemsBanner */ = { 464C6BFAA853DC755B9C1F60 /* PinnedItemsBanner */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -4030,6 +4039,15 @@
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
8656AFF06650360A5D0695FF /* EncryptionReset */ = {
isa = PBXGroup;
children = (
934A2E4A36A7FB6E301758EB /* EncryptionResetPasswordScreen */,
A3CF1DEFB89992E0B9187004 /* EncryptionResetScreen */,
);
path = EncryptionReset;
sourceTree = "<group>";
};
87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */ = { 87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -4168,6 +4186,18 @@
path = ElementCall; path = ElementCall;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
934A2E4A36A7FB6E301758EB /* EncryptionResetPasswordScreen */ = {
isa = PBXGroup;
children = (
E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */,
54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */,
303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */,
4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */,
459B661EA3598F9E709E81A7 /* View */,
);
path = EncryptionResetPasswordScreen;
sourceTree = "<group>";
};
93C7520ED23C9598BB144DBB /* UserProfileScreen */ = { 93C7520ED23C9598BB144DBB /* UserProfileScreen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -4389,6 +4419,18 @@
path = VoiceMessage; path = VoiceMessage;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A3CF1DEFB89992E0B9187004 /* EncryptionResetScreen */ = {
isa = PBXGroup;
children = (
E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */,
306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */,
5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */,
7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */,
D382E465AF067C1BF888BF8E /* View */,
);
path = EncryptionResetScreen;
sourceTree = "<group>";
};
A448A3A8F764174C60CD0CA1 /* Other */ = { A448A3A8F764174C60CD0CA1 /* Other */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -4861,6 +4903,14 @@
path = Layout; path = Layout;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D382E465AF067C1BF888BF8E /* View */ = {
isa = PBXGroup;
children = (
811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
D4B487C81A239A9C71807601 /* View */ = { D4B487C81A239A9C71807601 /* View */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -5002,6 +5052,7 @@
90DC2E28718955ED87AD1456 /* CreatePollScreen */, 90DC2E28718955ED87AD1456 /* CreatePollScreen */,
C18958141C8ED6D778F779A4 /* CreateRoom */, C18958141C8ED6D778F779A4 /* CreateRoom */,
F5A65D1D3B83593598DC278D /* EmojiPickerScreen */, F5A65D1D3B83593598DC278D /* EmojiPickerScreen */,
8656AFF06650360A5D0695FF /* EncryptionReset */,
448435400B561C40E514BE1C /* FilePreviewScreen */, 448435400B561C40E514BE1C /* FilePreviewScreen */,
8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */, 8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */,
B53CA9BECD3F97805E1432D0 /* HomeScreen */, B53CA9BECD3F97805E1432D0 /* HomeScreen */,
@@ -5135,18 +5186,6 @@
path = StartChatScreen; path = StartChatScreen;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
EE703B39AC7A2862CFDCA12C /* ResetKeyScreen */ = {
isa = PBXGroup;
children = (
E995E3F726488F8938F0BCD1 /* ResetRecoveryKeyScreenCoordinator.swift */,
76911C322BC4CD117A8A0AF1 /* ResetRecoveryKeyScreenModels.swift */,
C63616A8920EC6948B31EA1B /* ResetRecoveryKeyScreenViewModel.swift */,
99637028A8BD2843A35A92D4 /* ResetRecoveryKeyScreenViewModelProtocol.swift */,
01DF58ADE41080A419AD424A /* View */,
);
path = ResetKeyScreen;
sourceTree = "<group>";
};
EFD4F7FCAAAB3EF45EE7A067 /* BlockedUsersScreen */ = { EFD4F7FCAAAB3EF45EE7A067 /* BlockedUsersScreen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -6161,6 +6200,16 @@
B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */, B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */,
FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */, FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */,
46A6DB0F78FB399BD59E2D41 /* EncryptionKeyProviderProtocol.swift in Sources */, 46A6DB0F78FB399BD59E2D41 /* EncryptionKeyProviderProtocol.swift in Sources */,
0C6DF318E9C8F6461E6ABDE7 /* EncryptionResetPasswordScreen.swift in Sources */,
36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */,
B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */,
D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */,
A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */,
F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */,
3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */,
97BAEDD9054FB5F233EE928B /* EncryptionResetScreenModels.swift in Sources */,
EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */,
A0868BDE84D2140A885BE3C9 /* EncryptionResetScreenViewModelProtocol.swift in Sources */,
50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */, 50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */,
F78BAD28482A467287A9A5A3 /* EventBasedMessageTimelineItemProtocol.swift in Sources */, F78BAD28482A467287A9A5A3 /* EventBasedMessageTimelineItemProtocol.swift in Sources */,
02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */, 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */,
@@ -6406,11 +6455,6 @@
46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */, 46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */,
42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */, 42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */,
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */, 8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */,
9C9838B68C00C980A498050C /* ResetRecoveryKeyScreen.swift in Sources */,
3D2E3E1B01D4389DCBE8F0E8 /* ResetRecoveryKeyScreenCoordinator.swift in Sources */,
EC65AF0D9240A248DC9917BB /* ResetRecoveryKeyScreenModels.swift in Sources */,
E07ABB9FD1C87EBBDDE81DC5 /* ResetRecoveryKeyScreenViewModel.swift in Sources */,
680062C402ECB8FCAAE85A5C /* ResetRecoveryKeyScreenViewModelProtocol.swift in Sources */,
A494741843F087881299ACF0 /* RestorationToken.swift in Sources */, A494741843F087881299ACF0 /* RestorationToken.swift in Sources */,
6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */, 6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */,
8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */, 8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */,
@@ -7509,7 +7553,7 @@
repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift";
requirement = { requirement = {
kind = exactVersion; kind = exactVersion;
version = 1.0.29; version = 1.0.30;
}; };
}; };
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = {
@@ -149,8 +149,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/element-hq/matrix-rust-components-swift", "location" : "https://github.com/element-hq/matrix-rust-components-swift",
"state" : { "state" : {
"revision" : "d0226f669526e908d45bf9b5682f372d84cf9ffe", "revision" : "bc534e15fa0749d668b201b923ee57204afb868a",
"version" : "1.0.29" "version" : "1.0.30"
} }
}, },
{ {
@@ -81,6 +81,7 @@
"action_report_bug" = "Report bug"; "action_report_bug" = "Report bug";
"action_report_content" = "Report content"; "action_report_content" = "Report content";
"action_reset" = "Reset"; "action_reset" = "Reset";
"action_reset_identity" = "Reset identity";
"action_retry" = "Retry"; "action_retry" = "Retry";
"action_retry_decryption" = "Retry decryption"; "action_retry_decryption" = "Retry decryption";
"action_save" = "Save"; "action_save" = "Save";
@@ -429,12 +430,20 @@
"screen_edit_profile_error_title" = "Unable to update profile"; "screen_edit_profile_error_title" = "Unable to update profile";
"screen_edit_profile_title" = "Edit profile"; "screen_edit_profile_title" = "Edit profile";
"screen_edit_profile_updating_details" = "Updating profile…"; "screen_edit_profile_updating_details" = "Updating profile…";
"screen_encryption_reset_bullet_1" = "Your account details, contacts, preferences, and chat list will be kept";
"screen_encryption_reset_bullet_2" = "You will lose your existing message history";
"screen_encryption_reset_bullet_3" = "You will need to verify all your existing devices and contacts again";
"screen_encryption_reset_footer" = "Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key.";
"screen_encryption_reset_subtitle" = "If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app. ";
"screen_encryption_reset_title" = "Reset your identity in case you can’t confirm another way";
"screen_identity_confirmation_cannot_confirm" = "Can't confirm?";
"screen_identity_confirmation_create_new_recovery_key" = "Create a new recovery key"; "screen_identity_confirmation_create_new_recovery_key" = "Create a new recovery key";
"screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging."; "screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging.";
"screen_identity_confirmation_title" = "Confirm that it's you"; "screen_identity_confirmation_title" = "Confirm that it's you";
"screen_identity_confirmation_use_another_device" = "Use another device";
"screen_identity_confirmation_use_recovery_key" = "Use recovery key";
"screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device."; "screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device.";
"screen_identity_confirmed_title" = "Device verified"; "screen_identity_confirmed_title" = "Device verified";
"screen_identity_use_another_device" = "Use another device";
"screen_identity_waiting_on_other_device" = "Waiting on other device…"; "screen_identity_waiting_on_other_device" = "Waiting on other device…";
"screen_invites_decline_chat_message" = "Are you sure you want to decline the invitation to join %1$@?"; "screen_invites_decline_chat_message" = "Are you sure you want to decline the invitation to join %1$@?";
"screen_invites_decline_chat_title" = "Decline invite"; "screen_invites_decline_chat_title" = "Decline invite";
@@ -578,6 +587,12 @@
"screen_report_content_block_user_hint" = "Check if you want to hide all current and future messages from this user"; "screen_report_content_block_user_hint" = "Check if you want to hide all current and future messages from this user";
"screen_report_content_explanation" = "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages."; "screen_report_content_explanation" = "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages.";
"screen_report_content_hint" = "Reason for reporting this content"; "screen_report_content_hint" = "Reason for reporting this content";
"screen_reset_encryption_confirmation_alert_action" = "Yes, reset now";
"screen_reset_encryption_confirmation_alert_subtitle" = "This process is irreversible.";
"screen_reset_encryption_confirmation_alert_title" = "Are you sure you want to reset your encryption?";
"screen_reset_encryption_password_placeholder" = "Enter…";
"screen_reset_encryption_password_subtitle" = "Confirm that you want to reset your encryption.";
"screen_reset_encryption_password_title" = "Enter your account password to continue";
"screen_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias."; "screen_room_alias_resolver_resolve_alias_failure" = "Failed to resolve room alias.";
"screen_room_attachment_source_camera" = "Camera"; "screen_room_attachment_source_camera" = "Camera";
"screen_room_attachment_source_camera_video" = "Record video"; "screen_room_attachment_source_camera_video" = "Record video";
@@ -922,6 +937,7 @@
"screen_dm_details_unblock_user" = "Unblock user"; "screen_dm_details_unblock_user" = "Unblock user";
"screen_edit_poll_delete_confirmation_title" = "Delete Poll"; "screen_edit_poll_delete_confirmation_title" = "Delete Poll";
"screen_edit_poll_title" = "Edit poll"; "screen_edit_poll_title" = "Edit poll";
"screen_identity_use_another_device" = "Use another device";
"screen_login_subtitle" = "Matrix is an open network for secure, decentralised communication."; "screen_login_subtitle" = "Matrix is an open network for secure, decentralised communication.";
"screen_qr_code_login_invalid_scan_state_retry_button" = "Try again"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Try again";
"screen_report_content_block_user" = "Block user"; "screen_report_content_block_user" = "Block user";
@@ -26,6 +26,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
private let notificationManager: NotificationManagerProtocol private let notificationManager: NotificationManagerProtocol
private let rootNavigationStackCoordinator: NavigationStackCoordinator private let rootNavigationStackCoordinator: NavigationStackCoordinator
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let windowManager: WindowManagerProtocol
private let isNewLogin: Bool private let isNewLogin: Bool
private var navigationStackCoordinator: NavigationStackCoordinator! private var navigationStackCoordinator: NavigationStackCoordinator!
@@ -57,6 +58,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
notificationManager: NotificationManagerProtocol, notificationManager: NotificationManagerProtocol,
navigationStackCoordinator: NavigationStackCoordinator, navigationStackCoordinator: NavigationStackCoordinator,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
windowManager: WindowManagerProtocol,
isNewLogin: Bool) { isNewLogin: Bool) {
self.userSession = userSession self.userSession = userSession
self.appLockService = appLockService self.appLockService = appLockService
@@ -64,6 +66,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
self.appSettings = appSettings self.appSettings = appSettings
self.notificationManager = notificationManager self.notificationManager = notificationManager
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.windowManager = windowManager
self.isNewLogin = isNewLogin self.isNewLogin = isNewLogin
rootNavigationStackCoordinator = navigationStackCoordinator rootNavigationStackCoordinator = navigationStackCoordinator
@@ -215,7 +218,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
appSettings.hasRunIdentityConfirmationOnboarding = true appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.next) stateMachine.tryEvent(.next)
case .reset: case .reset:
presentResetRecoveryKeyScreen() presentEncryptionResetScreen()
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
@@ -262,8 +265,8 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
case .recoveryFixed: case .recoveryFixed:
appSettings.hasRunIdentityConfirmationOnboarding = true appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.next) stateMachine.tryEvent(.next)
case .showResetKeyInfo: case .resetEncryption:
presentResetRecoveryKeyScreen() presentEncryptionResetScreen()
default: default:
MXLog.error("Unexpected recovery action: \(action)") MXLog.error("Unexpected recovery action: \(action)")
} }
@@ -273,16 +276,32 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
presentCoordinator(coordinator) presentCoordinator(coordinator)
} }
private func presentResetRecoveryKeyScreen() { private func presentEncryptionResetScreen() {
let coordinator = ResetRecoveryKeyScreenCoordinator() let resetNavigationStackCoordinator = NavigationStackCoordinator()
let coordinator = EncryptionResetScreenCoordinator(parameters: .init(clientProxy: userSession.clientProxy,
navigationStackCoordinator: resetNavigationStackCoordinator,
userIndicatorController: userIndicatorController))
coordinator.actionsPublisher.sink { [weak self] action in coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }
switch action { switch action {
case .cancel: case .cancel:
self?.navigationStackCoordinator.setSheetCoordinator(nil) navigationStackCoordinator.setSheetCoordinator(nil)
case .requestOIDCAuthorisation(let url):
presentOIDCAuthorisationScreen(url: url)
case .resetFinished:
appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.next)
navigationStackCoordinator.setSheetCoordinator(nil)
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
navigationStackCoordinator.setSheetCoordinator(coordinator)
resetNavigationStackCoordinator.setRootCoordinator(coordinator)
navigationStackCoordinator.setSheetCoordinator(resetNavigationStackCoordinator)
} }
private func presentIdentityConfirmedScreen() { private func presentIdentityConfirmedScreen() {
@@ -361,4 +380,12 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
navigationStackCoordinator.push(coordinator) navigationStackCoordinator.push(coordinator)
} }
} }
private var accountSettingsPresenter: OIDCAccountSettingsPresenter?
private func presentOIDCAuthorisationScreen(url: URL) {
// Note to anyone in the future if you come back here to make this open in Safari instead of a WAS.
// As of iOS 16, there is an issue on the simulator with accessing the cookie but it works on a device. 🤷‍♂️
accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: url, presentationAnchor: windowManager.mainWindow)
accountSettingsPresenter?.start()
}
} }
@@ -153,10 +153,18 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
private func presentSecureBackupScreen(animated: Bool) { private func presentSecureBackupScreen(animated: Bool) {
let coordinator = SecureBackupScreenCoordinator(parameters: .init(appSettings: parameters.appSettings, let coordinator = SecureBackupScreenCoordinator(parameters: .init(appSettings: parameters.appSettings,
secureBackupController: parameters.userSession.clientProxy.secureBackupController, clientProxy: parameters.userSession.clientProxy,
navigationStackCoordinator: navigationStackCoordinator, navigationStackCoordinator: navigationStackCoordinator,
userIndicatorController: parameters.userIndicatorController)) userIndicatorController: parameters.userIndicatorController))
coordinator.actions.sink { [weak self] action in
switch action {
case .requestOIDCAuthorisation(let url):
self?.presentAccountManagementURL(url)
}
}
.store(in: &cancellables)
navigationStackCoordinator.push(coordinator, animated: animated) navigationStackCoordinator.push(coordinator, animated: animated)
} }
@@ -115,6 +115,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
notificationManager: notificationManager, notificationManager: notificationManager,
navigationStackCoordinator: detailNavigationStackCoordinator, navigationStackCoordinator: detailNavigationStackCoordinator,
userIndicatorController: ServiceLocator.shared.userIndicatorController, userIndicatorController: ServiceLocator.shared.userIndicatorController,
windowManager: appMediator.windowManager,
isNewLogin: isNewLogin) isNewLogin: isNewLogin)
setupStateMachine() setupStateMachine()
+32
View File
@@ -196,6 +196,8 @@ internal enum L10n {
internal static var actionReportContent: String { return L10n.tr("Localizable", "action_report_content") } internal static var actionReportContent: String { return L10n.tr("Localizable", "action_report_content") }
/// Reset /// Reset
internal static var actionReset: String { return L10n.tr("Localizable", "action_reset") } internal static var actionReset: String { return L10n.tr("Localizable", "action_reset") }
/// Reset identity
internal static var actionResetIdentity: String { return L10n.tr("Localizable", "action_reset_identity") }
/// Retry /// Retry
internal static var actionRetry: String { return L10n.tr("Localizable", "action_retry") } internal static var actionRetry: String { return L10n.tr("Localizable", "action_retry") }
/// Retry decryption /// Retry decryption
@@ -1045,12 +1047,30 @@ internal enum L10n {
internal static var screenEditProfileTitle: String { return L10n.tr("Localizable", "screen_edit_profile_title") } internal static var screenEditProfileTitle: String { return L10n.tr("Localizable", "screen_edit_profile_title") }
/// Updating profile… /// Updating profile…
internal static var screenEditProfileUpdatingDetails: String { return L10n.tr("Localizable", "screen_edit_profile_updating_details") } internal static var screenEditProfileUpdatingDetails: String { return L10n.tr("Localizable", "screen_edit_profile_updating_details") }
/// Your account details, contacts, preferences, and chat list will be kept
internal static var screenEncryptionResetBullet1: String { return L10n.tr("Localizable", "screen_encryption_reset_bullet_1") }
/// You will lose your existing message history
internal static var screenEncryptionResetBullet2: String { return L10n.tr("Localizable", "screen_encryption_reset_bullet_2") }
/// You will need to verify all your existing devices and contacts again
internal static var screenEncryptionResetBullet3: String { return L10n.tr("Localizable", "screen_encryption_reset_bullet_3") }
/// Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key.
internal static var screenEncryptionResetFooter: String { return L10n.tr("Localizable", "screen_encryption_reset_footer") }
/// If you’re not signed in to any other devices and you’ve lost your recovery key, then you’ll need to reset your identity to continue using the app.
internal static var screenEncryptionResetSubtitle: String { return L10n.tr("Localizable", "screen_encryption_reset_subtitle") }
/// Reset your identity in case you can’t confirm another way
internal static var screenEncryptionResetTitle: String { return L10n.tr("Localizable", "screen_encryption_reset_title") }
/// Can't confirm?
internal static var screenIdentityConfirmationCannotConfirm: String { return L10n.tr("Localizable", "screen_identity_confirmation_cannot_confirm") }
/// Create a new recovery key /// Create a new recovery key
internal static var screenIdentityConfirmationCreateNewRecoveryKey: String { return L10n.tr("Localizable", "screen_identity_confirmation_create_new_recovery_key") } internal static var screenIdentityConfirmationCreateNewRecoveryKey: String { return L10n.tr("Localizable", "screen_identity_confirmation_create_new_recovery_key") }
/// Verify this device to set up secure messaging. /// Verify this device to set up secure messaging.
internal static var screenIdentityConfirmationSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_subtitle") } internal static var screenIdentityConfirmationSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_subtitle") }
/// Confirm that it's you /// Confirm that it's you
internal static var screenIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_title") } internal static var screenIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_title") }
/// Use another device
internal static var screenIdentityConfirmationUseAnotherDevice: String { return L10n.tr("Localizable", "screen_identity_confirmation_use_another_device") }
/// Use recovery key
internal static var screenIdentityConfirmationUseRecoveryKey: String { return L10n.tr("Localizable", "screen_identity_confirmation_use_recovery_key") }
/// Now you can read or send messages securely, and anyone you chat with can also trust this device. /// Now you can read or send messages securely, and anyone you chat with can also trust this device.
internal static var screenIdentityConfirmedSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmed_subtitle") } internal static var screenIdentityConfirmedSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmed_subtitle") }
/// Device verified /// Device verified
@@ -1385,6 +1405,18 @@ internal enum L10n {
internal static var screenReportContentExplanation: String { return L10n.tr("Localizable", "screen_report_content_explanation") } internal static var screenReportContentExplanation: String { return L10n.tr("Localizable", "screen_report_content_explanation") }
/// Reason for reporting this content /// Reason for reporting this content
internal static var screenReportContentHint: String { return L10n.tr("Localizable", "screen_report_content_hint") } internal static var screenReportContentHint: String { return L10n.tr("Localizable", "screen_report_content_hint") }
/// Yes, reset now
internal static var screenResetEncryptionConfirmationAlertAction: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_action") }
/// This process is irreversible.
internal static var screenResetEncryptionConfirmationAlertSubtitle: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_subtitle") }
/// Are you sure you want to reset your encryption?
internal static var screenResetEncryptionConfirmationAlertTitle: String { return L10n.tr("Localizable", "screen_reset_encryption_confirmation_alert_title") }
/// Enter…
internal static var screenResetEncryptionPasswordPlaceholder: String { return L10n.tr("Localizable", "screen_reset_encryption_password_placeholder") }
/// Confirm that you want to reset your encryption.
internal static var screenResetEncryptionPasswordSubtitle: String { return L10n.tr("Localizable", "screen_reset_encryption_password_subtitle") }
/// Enter your account password to continue
internal static var screenResetEncryptionPasswordTitle: String { return L10n.tr("Localizable", "screen_reset_encryption_password_title") }
/// Failed to resolve room alias. /// Failed to resolve room alias.
internal static var screenRoomAliasResolverResolveAliasFailure: String { return L10n.tr("Localizable", "screen_room_alias_resolver_resolve_alias_failure") } internal static var screenRoomAliasResolverResolveAliasFailure: String { return L10n.tr("Localizable", "screen_room_alias_resolver_resolve_alias_failure") }
/// Camera /// Camera
@@ -4095,6 +4095,70 @@ class ClientProxyMock: ClientProxyProtocol {
return curve25519Base64ReturnValue return curve25519Base64ReturnValue
} }
} }
//MARK: - resetIdentity
var resetIdentityUnderlyingCallsCount = 0
var resetIdentityCallsCount: Int {
get {
if Thread.isMainThread {
return resetIdentityUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = resetIdentityUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
resetIdentityUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
resetIdentityUnderlyingCallsCount = newValue
}
}
}
}
var resetIdentityCalled: Bool {
return resetIdentityCallsCount > 0
}
var resetIdentityUnderlyingReturnValue: Result<IdentityResetHandle?, ClientProxyError>!
var resetIdentityReturnValue: Result<IdentityResetHandle?, ClientProxyError>! {
get {
if Thread.isMainThread {
return resetIdentityUnderlyingReturnValue
} else {
var returnValue: Result<IdentityResetHandle?, ClientProxyError>? = nil
DispatchQueue.main.sync {
returnValue = resetIdentityUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
resetIdentityUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
resetIdentityUnderlyingReturnValue = newValue
}
}
}
}
var resetIdentityClosure: (() async -> Result<IdentityResetHandle?, ClientProxyError>)?
func resetIdentity() async -> Result<IdentityResetHandle?, ClientProxyError> {
resetIdentityCallsCount += 1
if let resetIdentityClosure = resetIdentityClosure {
return await resetIdentityClosure()
} else {
return resetIdentityReturnValue
}
}
//MARK: - loadMediaContentForSource //MARK: - loadMediaContentForSource
var loadMediaContentForSourceThrowableError: Error? var loadMediaContentForSourceThrowableError: Error?
@@ -5915,6 +5915,75 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption {
} }
} }
//MARK: - resetIdentity
open var resetIdentityThrowableError: Error?
var resetIdentityUnderlyingCallsCount = 0
open var resetIdentityCallsCount: Int {
get {
if Thread.isMainThread {
return resetIdentityUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = resetIdentityUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
resetIdentityUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
resetIdentityUnderlyingCallsCount = newValue
}
}
}
}
open var resetIdentityCalled: Bool {
return resetIdentityCallsCount > 0
}
var resetIdentityUnderlyingReturnValue: IdentityResetHandle?
open var resetIdentityReturnValue: IdentityResetHandle? {
get {
if Thread.isMainThread {
return resetIdentityUnderlyingReturnValue
} else {
var returnValue: IdentityResetHandle?? = nil
DispatchQueue.main.sync {
returnValue = resetIdentityUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
resetIdentityUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
resetIdentityUnderlyingReturnValue = newValue
}
}
}
}
open var resetIdentityClosure: (() async throws -> IdentityResetHandle?)?
open override func resetIdentity() async throws -> IdentityResetHandle? {
if let error = resetIdentityThrowableError {
throw error
}
resetIdentityCallsCount += 1
if let resetIdentityClosure = resetIdentityClosure {
return try await resetIdentityClosure()
} else {
return resetIdentityReturnValue
}
}
//MARK: - resetRecoveryKey //MARK: - resetRecoveryKey
open var resetRecoveryKeyThrowableError: Error? open var resetRecoveryKeyThrowableError: Error?
@@ -7595,6 +7664,128 @@ open class HomeserverLoginDetailsSDKMock: MatrixRustSDK.HomeserverLoginDetails {
} }
} }
} }
open class IdentityResetHandleSDKMock: MatrixRustSDK.IdentityResetHandle {
init() {
super.init(noPointer: .init())
}
public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) {
fatalError("init(unsafeFromRawPointer:) has not been implemented")
}
fileprivate var pointer: UnsafeMutableRawPointer!
//MARK: - authType
var authTypeUnderlyingCallsCount = 0
open var authTypeCallsCount: Int {
get {
if Thread.isMainThread {
return authTypeUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = authTypeUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
authTypeUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
authTypeUnderlyingCallsCount = newValue
}
}
}
}
open var authTypeCalled: Bool {
return authTypeCallsCount > 0
}
var authTypeUnderlyingReturnValue: CrossSigningResetAuthType!
open var authTypeReturnValue: CrossSigningResetAuthType! {
get {
if Thread.isMainThread {
return authTypeUnderlyingReturnValue
} else {
var returnValue: CrossSigningResetAuthType? = nil
DispatchQueue.main.sync {
returnValue = authTypeUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
authTypeUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
authTypeUnderlyingReturnValue = newValue
}
}
}
}
open var authTypeClosure: (() -> CrossSigningResetAuthType)?
open override func authType() -> CrossSigningResetAuthType {
authTypeCallsCount += 1
if let authTypeClosure = authTypeClosure {
return authTypeClosure()
} else {
return authTypeReturnValue
}
}
//MARK: - reset
open var resetAuthThrowableError: Error?
var resetAuthUnderlyingCallsCount = 0
open var resetAuthCallsCount: Int {
get {
if Thread.isMainThread {
return resetAuthUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = resetAuthUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
resetAuthUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
resetAuthUnderlyingCallsCount = newValue
}
}
}
}
open var resetAuthCalled: Bool {
return resetAuthCallsCount > 0
}
open var resetAuthReceivedAuth: AuthData?
open var resetAuthReceivedInvocations: [AuthData?] = []
open var resetAuthClosure: ((AuthData?) async throws -> Void)?
open override func reset(auth: AuthData?) async throws {
if let error = resetAuthThrowableError {
throw error
}
resetAuthCallsCount += 1
resetAuthReceivedAuth = auth
DispatchQueue.main.async {
self.resetAuthReceivedInvocations.append(auth)
}
try await resetAuthClosure?(auth)
}
}
open class MediaFileHandleSDKMock: MatrixRustSDK.MediaFileHandle { open class MediaFileHandleSDKMock: MatrixRustSDK.MediaFileHandle {
init() { init() {
super.init(noPointer: .init()) super.init(noPointer: .init())
@@ -58,12 +58,11 @@ struct RoundedLabelItem<Icon: View>: View {
private struct CheckmarkLabelStyle: LabelStyle { private struct CheckmarkLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View { func makeBody(configuration: Configuration) -> some View {
HStack(alignment: .firstTextBaseline, spacing: 16) { HStack(alignment: .top, spacing: 16) {
configuration.icon configuration.icon
.font(.compound.bodyLGSemibold)
configuration.title configuration.title
.font(.compound.bodyMDSemibold)
} }
.font(.compound.bodyMD)
.foregroundColor(.compound.textPrimary) .foregroundColor(.compound.textPrimary)
} }
} }
@@ -0,0 +1,68 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// periphery:ignore:all - this is just a encryptionResetPassword remove this comment once generating the final file
import Combine
import SwiftUI
struct EncryptionResetPasswordScreenCoordinatorParameters { }
enum EncryptionResetPasswordScreenCoordinatorAction: CustomStringConvertible {
case resetIdentity(String)
var description: String {
switch self {
case .resetIdentity:
"resetIdentity"
}
}
}
final class EncryptionResetPasswordScreenCoordinator: CoordinatorProtocol {
private let parameters: EncryptionResetPasswordScreenCoordinatorParameters
private let viewModel: EncryptionResetPasswordScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<EncryptionResetPasswordScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetPasswordScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(parameters: EncryptionResetPasswordScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = EncryptionResetPasswordScreenViewModel()
}
func start() {
viewModel.actionsPublisher.sink { [weak self] action in
MXLog.info("Coordinator: received view model action: \(action)")
guard let self else { return }
switch action {
case .resetIdentity(let password):
self.actionsSubject.send(.resetIdentity(password))
}
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(EncryptionResetPasswordScreen(context: viewModel.context))
}
}
@@ -0,0 +1,41 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
enum EncryptionResetPasswordScreenViewModelAction: CustomStringConvertible {
case resetIdentity(String)
var description: String {
switch self {
case .resetIdentity:
"resetIdentity"
}
}
}
struct EncryptionResetPasswordScreenViewState: BindableState {
var bindings: EncryptionResetPasswordScreenViewStateBindings
}
struct EncryptionResetPasswordScreenViewStateBindings {
var password: String
var alertInfo: AlertInfo<UUID>?
}
enum EncryptionResetPasswordScreenViewAction {
case resetIdentity
}
@@ -0,0 +1,42 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
import SwiftUI
typealias EncryptionResetPasswordScreenViewModelType = StateStoreViewModel<EncryptionResetPasswordScreenViewState, EncryptionResetPasswordScreenViewAction>
class EncryptionResetPasswordScreenViewModel: EncryptionResetPasswordScreenViewModelType, EncryptionResetPasswordScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<EncryptionResetPasswordScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetPasswordScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
super.init(initialViewState: .init(bindings: .init(password: "")))
}
// MARK: - Public
override func process(viewAction: EncryptionResetPasswordScreenViewAction) {
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .resetIdentity:
actionsSubject.send(.resetIdentity(state.bindings.password))
}
}
}
@@ -17,7 +17,7 @@
import Combine import Combine
@MainActor @MainActor
protocol ResetRecoveryKeyScreenViewModelProtocol { protocol EncryptionResetPasswordScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<ResetRecoveryKeyScreenViewModelAction, Never> { get } var actionsPublisher: AnyPublisher<EncryptionResetPasswordScreenViewModelAction, Never> { get }
var context: ResetRecoveryKeyScreenViewModelType.Context { get } var context: EncryptionResetPasswordScreenViewModelType.Context { get }
} }
@@ -0,0 +1,83 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Compound
import SwiftUI
struct EncryptionResetPasswordScreen: View {
@ObservedObject var context: EncryptionResetPasswordScreenViewModel.Context
@FocusState private var textFieldFocus
var body: some View {
FullscreenDialog {
VStack(spacing: 16) {
HeroImage(icon: \.lockSolid)
Text(L10n.screenResetEncryptionPasswordTitle)
.foregroundColor(.compound.textPrimary)
.font(.compound.headingMDBold)
.multilineTextAlignment(.center)
Text(L10n.screenResetEncryptionPasswordSubtitle)
.foregroundColor(.compound.textSecondary)
.font(.compound.bodyMD)
.multilineTextAlignment(.center)
passwordSection
}
.padding(16)
} bottomContent: {
Button(L10n.actionResetIdentity, role: .destructive) {
context.send(viewAction: .resetIdentity)
}
.buttonStyle(.compound(.primary))
}
.backgroundStyle(.compound.bgCanvasDefault)
.interactiveDismissDisabled()
.onAppear { textFieldFocus = true }
}
@ViewBuilder
private var passwordSection: some View {
VStack(alignment: .leading, spacing: 8) {
Text(L10n.commonPassword)
.foregroundColor(.compound.textPrimary)
.font(.compound.bodySMSemibold)
SecureField(L10n.screenResetEncryptionPasswordPlaceholder, text: $context.password)
.frame(maxWidth: .infinity)
.padding()
.background(Color.compound.bgSubtleSecondaryLevel0)
.clipShape(RoundedRectangle(cornerRadius: 8))
.focused($textFieldFocus)
.submitLabel(.done)
.onSubmit {
context.send(viewAction: .resetIdentity)
}
}
}
}
// MARK: - Previews
struct EncryptionResetPasswordScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = EncryptionResetPasswordScreenViewModel()
static var previews: some View {
NavigationStack {
EncryptionResetPasswordScreen(context: viewModel.context)
}
}
}
@@ -0,0 +1,90 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
import SwiftUI
enum EncryptionResetScreenCoordinatorAction {
case cancel
case requestOIDCAuthorisation(URL)
case resetFinished
}
struct EncryptionResetScreenCoordinatorParameters {
let clientProxy: ClientProxyProtocol
let navigationStackCoordinator: NavigationStackCoordinator
let userIndicatorController: UserIndicatorControllerProtocol
}
final class EncryptionResetScreenCoordinator: CoordinatorProtocol {
private let parameters: EncryptionResetScreenCoordinatorParameters
private let viewModel: EncryptionResetScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<EncryptionResetScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(parameters: EncryptionResetScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = EncryptionResetScreenViewModel(clientProxy: parameters.clientProxy,
userIndicatorController: parameters.userIndicatorController)
}
func start() {
viewModel.actionsPublisher.sink { [weak self] action in
MXLog.info("Coordinator: received view model action: \(action)")
guard let self else { return }
switch action {
case .requestPassword:
presentPasswordScreen()
case .requestOIDCAuthorisation(let url):
self.actionsSubject.send(.requestOIDCAuthorisation(url))
case .resetFinished:
self.actionsSubject.send(.resetFinished)
case .cancel:
self.actionsSubject.send(.cancel)
}
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(EncryptionResetScreen(context: viewModel.context))
}
// MARK: - Private
private func presentPasswordScreen() {
let coordinator = EncryptionResetPasswordScreenCoordinator(parameters: .init())
coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }
switch action {
case .resetIdentity(let password):
viewModel.continueResetFlowWith(password: password)
parameters.navigationStackCoordinator.pop()
}
}
.store(in: &cancellables)
parameters.navigationStackCoordinator.push(coordinator)
}
}
@@ -16,11 +16,14 @@
import Foundation import Foundation
enum ResetRecoveryKeyScreenViewModelAction { enum EncryptionResetScreenViewModelAction {
case requestPassword
case requestOIDCAuthorisation(url: URL)
case resetFinished
case cancel case cancel
} }
struct ResetRecoveryKeyScreenViewState: BindableState { struct EncryptionResetScreenViewState: BindableState {
private let listItem3AttributedText = { private let listItem3AttributedText = {
let boldPlaceholder = "{bold}" let boldPlaceholder = "{bold}"
var finalString = AttributedString(L10n.screenCreateNewRecoveryKeyListItem3(boldPlaceholder)) var finalString = AttributedString(L10n.screenCreateNewRecoveryKeyListItem3(boldPlaceholder))
@@ -39,8 +42,15 @@ struct ResetRecoveryKeyScreenViewState: BindableState {
AttributedString(L10n.screenCreateNewRecoveryKeyListItem5) AttributedString(L10n.screenCreateNewRecoveryKeyListItem5)
] ]
} }
var bindings: EncryptionResetScreenViewStateBindings
} }
enum ResetRecoveryKeyScreenViewAction { struct EncryptionResetScreenViewStateBindings {
var alertInfo: AlertInfo<UUID>?
}
enum EncryptionResetScreenViewAction {
case reset
case cancel case cancel
} }
@@ -0,0 +1,156 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
import MatrixRustSDK
import SwiftUI
typealias EncryptionResetScreenViewModelType = StateStoreViewModel<EncryptionResetScreenViewState, EncryptionResetScreenViewAction>
class EncryptionResetScreenViewModel: EncryptionResetScreenViewModelType, EncryptionResetScreenViewModelProtocol {
private let clientProxy: ClientProxyProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<EncryptionResetScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<EncryptionResetScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
private var identityResetHandle: IdentityResetHandle?
init(clientProxy: ClientProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol) {
self.clientProxy = clientProxy
self.userIndicatorController = userIndicatorController
super.init(initialViewState: EncryptionResetScreenViewState(bindings: .init()))
}
// MARK: - Public
override func process(viewAction: EncryptionResetScreenViewAction) {
switch viewAction {
case .reset:
state.bindings.alertInfo = .init(id: UUID(),
title: L10n.screenResetEncryptionConfirmationAlertTitle,
message: L10n.screenResetEncryptionConfirmationAlertSubtitle,
primaryButton: .init(title: L10n.screenResetEncryptionConfirmationAlertAction, role: .destructive, action: { [weak self] in
guard let self else { return }
Task { await self.startResetFlow() }
}))
case .cancel:
actionsSubject.send(.cancel)
}
}
func continueResetFlowWith(password: String) {
Task {
await resetWith(password: password)
}
}
// MARK: - Private
private func startResetFlow() async {
showLoadingIndicator()
defer {
hideLoadingIndicator()
}
switch await clientProxy.resetIdentity() {
case .success(let handle):
// If the handle is missing then interactive authentication wasn't
// necessary and the reset proceeded as normal
guard let handle else {
actionsSubject.send(.resetFinished)
return
}
identityResetHandle = handle
switch handle.authType() {
case .uiaa:
actionsSubject.send(.requestPassword)
case .oidc(let oidcInfo):
guard let url = URL(string: oidcInfo.approvalUrl) else {
fatalError("Invalid URL received through identity reset handle: \(oidcInfo.approvalUrl)")
}
hideLoadingIndicator()
actionsSubject.send(.requestOIDCAuthorisation(url: url))
await resetWithOIDCAuthorisation()
}
case .failure(let error):
MXLog.error("Failed resetting encryption with error \(error)")
showErrorToast()
}
}
func resetWith(password: String) async {
guard let identityResetHandle else {
fatalError("Requested reset flow continuation without a stored handle")
}
showLoadingIndicator()
defer {
hideLoadingIndicator()
}
do {
try await identityResetHandle.reset(auth: .password(passwordDetails: .init(identifier: clientProxy.userID, password: password)))
actionsSubject.send(.resetFinished)
} catch {
MXLog.error("Failed resetting encryption with error \(error)")
showErrorToast()
}
}
private func resetWithOIDCAuthorisation() async {
guard let identityResetHandle else {
fatalError("Requested reset flow continuation without a stored handle")
}
do {
try await identityResetHandle.reset(auth: nil)
actionsSubject.send(.resetFinished)
} catch {
MXLog.error("Failed resetting encryption with error \(error)")
showErrorToast()
}
}
// MARK: Toasts and loading indicators
private static let loadingIndicatorIdentifier = "\(EncryptionResetScreenViewModel.self)-Loading"
private func showLoadingIndicator() {
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
}
private func hideLoadingIndicator() {
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
private func showErrorToast() {
userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown))
}
}
@@ -0,0 +1,25 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
@MainActor
protocol EncryptionResetScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<EncryptionResetScreenViewModelAction, Never> { get }
var context: EncryptionResetScreenViewModelType.Context { get }
func continueResetFlowWith(password: String)
}
@@ -0,0 +1,119 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Compound
import SwiftUI
struct EncryptionResetScreen: View {
@ObservedObject var context: EncryptionResetScreenViewModel.Context
var body: some View {
FullscreenDialog {
mainContent
} bottomContent: {
Button(L10n.actionContinue, role: .destructive) {
context.send(viewAction: .reset)
}
.buttonStyle(.compound(.primary))
}
.background()
.backgroundStyle(.compound.bgSubtleSecondary)
.interactiveDismissDisabled()
.toolbar { toolbar }
.toolbar(.visible, for: .navigationBar)
.alert(item: $context.alertInfo)
}
/// The main content of the screen that is shown inside the scroll view.
private var mainContent: some View {
VStack(spacing: 24) {
header
checkmarkList
footer
}
}
private var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.error, style: .critical)
.padding(.bottom, 8)
Text(L10n.screenEncryptionResetTitle)
.font(.compound.headingMDBold)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textPrimary)
Text(L10n.screenEncryptionResetSubtitle)
.font(.compound.bodyMD)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textSecondary)
}
}
private var footer: some View {
Text(L10n.screenEncryptionResetFooter)
.font(.compound.bodyMDSemibold)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textPrimary)
}
/// The list of re-assurances about analytics.
private var checkmarkList: some View {
VStack(alignment: .leading, spacing: 4) {
checkMarkItem(title: L10n.screenEncryptionResetBullet1, position: .top, positive: true)
checkMarkItem(title: L10n.screenEncryptionResetBullet2, position: .middle, positive: false)
checkMarkItem(title: L10n.screenEncryptionResetBullet3, position: .bottom, positive: false)
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity)
.environment(\.backgroundStyle, AnyShapeStyle(.compound.bgSubtleSecondary))
}
@ViewBuilder
private func checkMarkItem(title: String, position: ListPosition, positive: Bool) -> some View {
RoundedLabelItem(title: title, listPosition: position) {
if positive {
CompoundIcon(\.check)
.foregroundColor(.compound.iconAccentPrimary)
} else {
CompoundIcon(\.close)
.foregroundColor(.compound.iconCriticalPrimary)
}
}
.backgroundStyle(.compound.bgCanvasDefault)
}
@ToolbarContentBuilder
private var toolbar: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button(L10n.actionCancel) {
context.send(viewAction: .cancel)
}
}
}
}
// MARK: - Previews
struct EncryptionResetScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = EncryptionResetScreenViewModel(clientProxy: ClientProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock())
static var previews: some View {
NavigationStack {
EncryptionResetScreen(context: viewModel.context)
}
}
}
@@ -14,6 +14,7 @@
// limitations under the License. // limitations under the License.
// //
import Compound
import SwiftUI import SwiftUI
/// A prompt that asks the user whether they would like to enable Analytics or not. /// A prompt that asks the user whether they would like to enable Analytics or not.
@@ -58,14 +59,6 @@ struct AnalyticsPromptScreen: View {
.foregroundColor(.compound.textSecondary) .foregroundColor(.compound.textSecondary)
} }
} }
@ViewBuilder
private var checkMark: some View {
Image(systemName: "checkmark.circle")
.symbolVariant(.fill)
.symbolRenderingMode(.palette)
.foregroundStyle(Color.compound.iconAccentTertiary, Color.compound.textOnSolidPrimary)
}
/// The list of re-assurances about analytics. /// The list of re-assurances about analytics.
private var checkmarkList: some View { private var checkmarkList: some View {
@@ -82,7 +75,8 @@ struct AnalyticsPromptScreen: View {
@ViewBuilder @ViewBuilder
private func checkMarkItem(title: String, position: ListPosition) -> some View { private func checkMarkItem(title: String, position: ListPosition) -> some View {
RoundedLabelItem(title: title, listPosition: position) { RoundedLabelItem(title: title, listPosition: position) {
checkMark CompoundIcon(\.checkCircle, size: .small, relativeTo: .body)
.foregroundColor(.compound.iconAccentPrimary)
} }
} }
@@ -70,21 +70,21 @@ struct IdentityConfirmationScreen: View {
@ViewBuilder @ViewBuilder
private var actionButtons: some View { private var actionButtons: some View {
VStack(spacing: 32) { VStack(spacing: 16) {
if context.viewState.availableActions.contains(.interactiveVerification) { if context.viewState.availableActions.contains(.interactiveVerification) {
Button(L10n.actionStartVerification) { Button(L10n.screenIdentityConfirmationUseAnotherDevice) {
context.send(viewAction: .otherDevice) context.send(viewAction: .otherDevice)
} }
.buttonStyle(.compound(.primary)) .buttonStyle(.compound(.primary))
if context.viewState.availableActions.contains(.recovery) { if context.viewState.availableActions.contains(.recovery) {
Button(L10n.screenSessionVerificationEnterRecoveryKey) { Button(L10n.screenIdentityConfirmationUseRecoveryKey) {
context.send(viewAction: .recoveryKey) context.send(viewAction: .recoveryKey)
} }
.buttonStyle(.compound(.plain)) .buttonStyle(.compound(.secondary))
} }
} else if context.viewState.availableActions.contains(.recovery) { } else if context.viewState.availableActions.contains(.recovery) {
Button(L10n.screenSessionVerificationEnterRecoveryKey) { Button(L10n.screenIdentityConfirmationUseRecoveryKey) {
context.send(viewAction: .recoveryKey) context.send(viewAction: .recoveryKey)
} }
.buttonStyle(.compound(.primary)) .buttonStyle(.compound(.primary))
@@ -97,10 +97,11 @@ struct IdentityConfirmationScreen: View {
.buttonStyle(.compound(.plain)) .buttonStyle(.compound(.plain))
} }
Button(L10n.screenRecoveryKeyConfirmLostRecoveryKey, role: .destructive) { Button(L10n.screenIdentityConfirmationCannotConfirm) {
context.send(viewAction: .reset) context.send(viewAction: .reset)
} }
.buttonStyle(.compound(.plain)) .buttonStyle(.compound(.plain))
.padding(.vertical, 14)
} }
} }
} }
@@ -112,11 +113,13 @@ struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview {
NavigationStack { NavigationStack {
IdentityConfirmationScreen(context: viewModel.context) IdentityConfirmationScreen(context: viewModel.context)
} }
.snapshot(delay: 0.25)
} }
private static var viewModel: IdentityConfirmationScreenViewModel { private static var viewModel: IdentityConfirmationScreenViewModel {
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@user:example.com", let clientProxy = ClientProxyMock(.init())
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))))))) let userSession = UserSessionMock(.init(clientProxy: clientProxy))
userSession.sessionSecurityStatePublisher = CurrentValuePublisher<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: .enabled))
return IdentityConfirmationScreenViewModel(userSession: userSession, return IdentityConfirmationScreenViewModel(userSession: userSession,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
@@ -1,56 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// periphery:ignore:all - this is just a resetKey remove this comment once generating the final file
import Combine
import SwiftUI
enum ResetRecoveryKeyScreenCoordinatorAction {
case cancel
}
final class ResetRecoveryKeyScreenCoordinator: CoordinatorProtocol {
private let viewModel: ResetRecoveryKeyScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<ResetRecoveryKeyScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<ResetRecoveryKeyScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
viewModel = ResetRecoveryKeyScreenViewModel()
}
func start() {
viewModel.actionsPublisher.sink { [weak self] action in
MXLog.info("Coordinator: received view model action: \(action)")
guard let self else { return }
switch action {
case .cancel:
self.actionsSubject.send(.cancel)
}
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(ResetRecoveryKeyScreen(context: viewModel.context))
}
}
@@ -1,41 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
import SwiftUI
typealias ResetRecoveryKeyScreenViewModelType = StateStoreViewModel<ResetRecoveryKeyScreenViewState, ResetRecoveryKeyScreenViewAction>
class ResetRecoveryKeyScreenViewModel: ResetRecoveryKeyScreenViewModelType, ResetRecoveryKeyScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<ResetRecoveryKeyScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<ResetRecoveryKeyScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
super.init(initialViewState: ResetRecoveryKeyScreenViewState())
}
// MARK: - Public
override func process(viewAction: ResetRecoveryKeyScreenViewAction) {
switch viewAction {
case .cancel:
// We might also need to display first an alert and do a logOut API call in some cases
actionsSubject.send(.cancel)
}
}
}
@@ -1,75 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Compound
import SwiftUI
struct ResetRecoveryKeyScreen: View {
@ObservedObject var context: ResetRecoveryKeyScreenViewModel.Context
var body: some View {
NavigationStack {
FullscreenDialog {
mainContent
} bottomContent: {
EmptyView()
}
.toolbar { toolbar }
.toolbar(.visible, for: .navigationBar)
.background()
.backgroundStyle(.compound.bgSubtleSecondary)
.interactiveDismissDisabled()
}
}
private var mainContent: some View {
VStack(spacing: 40) {
header
SFNumberedListView(items: context.viewState.listItems)
}
}
private var header: some View {
VStack(spacing: 16) {
HeroImage(icon: \.computer, style: .subtle)
Text(L10n.screenCreateNewRecoveryKeyTitle)
.foregroundColor(.compound.textPrimary)
.font(.compound.headingMDBold)
.multilineTextAlignment(.center)
}
}
@ToolbarContentBuilder
private var toolbar: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button(L10n.actionCancel) {
context.send(viewAction: .cancel)
}
}
}
}
// MARK: - Previews
struct ResetRecoveryKeyScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = ResetRecoveryKeyScreenViewModel()
static var previews: some View {
NavigationStack {
ResetRecoveryKeyScreen(context: viewModel.context)
}
}
}
@@ -28,7 +28,7 @@ enum SecureBackupRecoveryKeyScreenCoordinatorAction {
case recoverySetUp case recoverySetUp
case recoveryChanged case recoveryChanged
case recoveryFixed case recoveryFixed
case showResetKeyInfo case resetEncryption
} }
final class SecureBackupRecoveryKeyScreenCoordinator: CoordinatorProtocol { final class SecureBackupRecoveryKeyScreenCoordinator: CoordinatorProtocol {
@@ -65,8 +65,8 @@ final class SecureBackupRecoveryKeyScreenCoordinator: CoordinatorProtocol {
case .unknown: case .unknown:
fatalError() fatalError()
} }
case .showResetKeyInfo: case .resetEncryption:
self.actionsSubject.send(.showResetKeyInfo) self.actionsSubject.send(.resetEncryption)
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
@@ -19,7 +19,7 @@ import Foundation
enum SecureBackupRecoveryKeyScreenViewModelAction { enum SecureBackupRecoveryKeyScreenViewModelAction {
case done(mode: SecureBackupRecoveryKeyScreenViewMode) case done(mode: SecureBackupRecoveryKeyScreenViewMode)
case cancel case cancel
case showResetKeyInfo case resetEncryption
} }
enum SecureBackupRecoveryKeyScreenViewMode { enum SecureBackupRecoveryKeyScreenViewMode {
@@ -90,7 +90,7 @@ enum SecureBackupRecoveryKeyScreenViewAction {
case copyKey case copyKey
case keySaved case keySaved
case confirmKey case confirmKey
case resetKey case resetEncryption
case done case done
case cancel case cancel
} }
@@ -40,13 +40,12 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
secureBackupController.recoveryState secureBackupController.recoveryState
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak userIndicatorController] state in .sink(receiveValue: { [weak self] state in
let loadingIndicatorIdentifier = "SecureBackupRecoveryKeyScreenLoading"
switch state { switch state {
case .settingUp: case .settingUp:
userIndicatorController?.submitIndicator(.init(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true)) self?.showLoadingIndicator()
default: default:
userIndicatorController?.retractIndicatorWithId(loadingIndicatorIdentifier) self?.hideLoadingIndicator()
} }
}) })
.store(in: &cancellables) .store(in: &cancellables)
@@ -67,6 +66,8 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
MXLog.error("Failed generating recovery key with error: \(error)") MXLog.error("Failed generating recovery key with error: \(error)")
state.bindings.alertInfo = .init(id: .init()) state.bindings.alertInfo = .init(id: .init())
} }
hideLoadingIndicator()
} }
case .copyKey: case .copyKey:
UIPasteboard.general.string = state.recoveryKey UIPasteboard.general.string = state.recoveryKey
@@ -76,8 +77,7 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
state.doneButtonEnabled = true state.doneButtonEnabled = true
case .confirmKey: case .confirmKey:
Task { Task {
let loadingIndicatorIdentifier = "SecureBackupRecoveryKeyScreen" showLoadingIndicator()
userIndicatorController.submitIndicator(.init(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true))
switch await secureBackupController.confirmRecoveryKey(state.bindings.confirmationRecoveryKey) { switch await secureBackupController.confirmRecoveryKey(state.bindings.confirmationRecoveryKey) {
case .success: case .success:
@@ -87,7 +87,7 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
state.bindings.alertInfo = .init(id: .init()) state.bindings.alertInfo = .init(id: .init())
} }
userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier) hideLoadingIndicator()
} }
case .cancel: case .cancel:
actionsSubject.send(.cancel) actionsSubject.send(.cancel)
@@ -100,10 +100,23 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
guard let self else { return } guard let self else { return }
actionsSubject.send(.done(mode: context.viewState.mode)) actionsSubject.send(.done(mode: context.viewState.mode))
})) }))
case .resetKey: case .resetEncryption:
actionsSubject.send(.showResetKeyInfo) actionsSubject.send(.resetEncryption)
} }
} }
private static let loadingIndicatorIdentifier = "\(SecureBackupRecoveryKeyScreenViewModel.self)-Loading"
private func showLoadingIndicator() {
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
}
private func hideLoadingIndicator() {
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}
} }
extension SecureBackupRecoveryState { extension SecureBackupRecoveryState {
@@ -101,7 +101,7 @@ struct SecureBackupRecoveryKeyScreen: View {
.disabled(context.confirmationRecoveryKey.isEmpty) .disabled(context.confirmationRecoveryKey.isEmpty)
Button { Button {
context.send(viewAction: .resetKey) context.send(viewAction: .resetEncryption)
} label: { } label: {
Text(L10n.screenIdentityConfirmationCreateNewRecoveryKey) Text(L10n.screenIdentityConfirmationCreateNewRecoveryKey)
.padding(.vertical, 14) .padding(.vertical, 14)
@@ -205,9 +205,6 @@ struct SecureBackupRecoveryKeyScreen: View {
.font(.compound.bodySMSemibold) .font(.compound.bodySMSemibold)
SecureField(L10n.screenRecoveryKeyConfirmKeyPlaceholder, text: $context.confirmationRecoveryKey) SecureField(L10n.screenRecoveryKeyConfirmKeyPlaceholder, text: $context.confirmationRecoveryKey)
.textContentType(.password) // Not ideal but stops random suggestions
.autocapitalization(.none)
.disableAutocorrection(true)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding() .padding()
.background(Color.compound.bgSubtleSecondaryLevel0) .background(Color.compound.bgSubtleSecondaryLevel0)
@@ -19,20 +19,30 @@ import SwiftUI
struct SecureBackupScreenCoordinatorParameters { struct SecureBackupScreenCoordinatorParameters {
let appSettings: AppSettings let appSettings: AppSettings
let secureBackupController: SecureBackupControllerProtocol let clientProxy: ClientProxyProtocol
weak var navigationStackCoordinator: NavigationStackCoordinator? weak var navigationStackCoordinator: NavigationStackCoordinator?
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
} }
enum SecureBackupScreenCoordinatorAction {
case requestOIDCAuthorisation(URL)
}
final class SecureBackupScreenCoordinator: CoordinatorProtocol { final class SecureBackupScreenCoordinator: CoordinatorProtocol {
private let parameters: SecureBackupScreenCoordinatorParameters private let parameters: SecureBackupScreenCoordinatorParameters
private var viewModel: SecureBackupScreenViewModelProtocol private var viewModel: SecureBackupScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<SecureBackupScreenCoordinatorAction, Never> = .init()
var actions: AnyPublisher<SecureBackupScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(parameters: SecureBackupScreenCoordinatorParameters) { init(parameters: SecureBackupScreenCoordinatorParameters) {
self.parameters = parameters self.parameters = parameters
viewModel = SecureBackupScreenViewModel(secureBackupController: parameters.secureBackupController, viewModel = SecureBackupScreenViewModel(secureBackupController: parameters.clientProxy.secureBackupController,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
chatBackupDetailsURL: parameters.appSettings.chatBackupDetailsURL) chatBackupDetailsURL: parameters.appSettings.chatBackupDetailsURL)
} }
@@ -43,9 +53,9 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
switch action { switch action {
case .recoveryKey: case .recoveryKey:
let navigationStackCoordinator = NavigationStackCoordinator() let recoveryNavigationStackCoordinator = NavigationStackCoordinator()
let recoveryKeyCoordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: .init(secureBackupController: parameters.secureBackupController, let recoveryKeyCoordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: .init(secureBackupController: parameters.clientProxy.secureBackupController,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
isModallyPresented: true)) isModallyPresented: true))
@@ -63,19 +73,19 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
case .recoveryFixed: case .recoveryFixed:
showSuccessIndicator(title: L10n.screenRecoveryKeyConfirmSuccess) showSuccessIndicator(title: L10n.screenRecoveryKeyConfirmSuccess)
parameters.navigationStackCoordinator?.setSheetCoordinator(nil) parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
case .showResetKeyInfo: case .resetEncryption:
showResetRecoveryKeyScreen(navigationStackCoordinator: navigationStackCoordinator) showEncryptionReset(recoveryNavigationStackCoordinator: recoveryNavigationStackCoordinator)
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
navigationStackCoordinator.setRootCoordinator(recoveryKeyCoordinator, animated: true) recoveryNavigationStackCoordinator.setRootCoordinator(recoveryKeyCoordinator, animated: true)
parameters.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator) parameters.navigationStackCoordinator?.setSheetCoordinator(recoveryNavigationStackCoordinator)
case .keyBackup: case .keyBackup:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let keyBackupCoordinator = SecureBackupKeyBackupScreenCoordinator(parameters: .init(secureBackupController: parameters.secureBackupController, let keyBackupCoordinator = SecureBackupKeyBackupScreenCoordinator(parameters: .init(secureBackupController: parameters.clientProxy.secureBackupController,
userIndicatorController: parameters.userIndicatorController)) userIndicatorController: parameters.userIndicatorController))
keyBackupCoordinator.actions.sink { [weak self] action in keyBackupCoordinator.actions.sink { [weak self] action in
@@ -108,15 +118,30 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
persistent: false)) persistent: false))
} }
private func showResetRecoveryKeyScreen(navigationStackCoordinator: NavigationStackCoordinator) { private func showEncryptionReset(recoveryNavigationStackCoordinator: NavigationStackCoordinator) {
let coordinator = ResetRecoveryKeyScreenCoordinator() let resetNavigationStackCoordinator = NavigationStackCoordinator()
coordinator.actionsPublisher.sink { action in
let coordinator = EncryptionResetScreenCoordinator(parameters: .init(clientProxy: parameters.clientProxy,
navigationStackCoordinator: resetNavigationStackCoordinator,
userIndicatorController: parameters.userIndicatorController))
coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }
switch action { switch action {
case .cancel: case .cancel:
navigationStackCoordinator.setSheetCoordinator(nil) recoveryNavigationStackCoordinator.setSheetCoordinator(nil)
case .requestOIDCAuthorisation(let url):
actionsSubject.send(.requestOIDCAuthorisation(url))
case .resetFinished:
parameters.navigationStackCoordinator?.setSheetCoordinator(nil) // Dismiss the recovery screen
recoveryNavigationStackCoordinator.setSheetCoordinator(nil)
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
navigationStackCoordinator.setSheetCoordinator(coordinator)
resetNavigationStackCoordinator.setRootCoordinator(coordinator)
recoveryNavigationStackCoordinator.setSheetCoordinator(resetNavigationStackCoordinator)
} }
} }
@@ -42,12 +42,12 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
private var viewModel: SettingsScreenViewModelProtocol private var viewModel: SettingsScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<SettingsScreenCoordinatorAction, Never> = .init() private let actionsSubject: PassthroughSubject<SettingsScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
var actions: AnyPublisher<SettingsScreenCoordinatorAction, Never> { var actions: AnyPublisher<SettingsScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
private var cancellables = Set<AnyCancellable>()
// MARK: - Setup // MARK: - Setup
init(parameters: SettingsScreenCoordinatorParameters) { init(parameters: SettingsScreenCoordinatorParameters) {
@@ -883,7 +883,7 @@ class ClientProxy: ClientProxyProtocol {
} }
} }
// MARK: - Encryption // MARK: - Crypto
func ed25519Base64() async -> String? { func ed25519Base64() async -> String? {
await client.encryption().ed25519Key() await client.encryption().ed25519Key()
@@ -892,6 +892,14 @@ class ClientProxy: ClientProxyProtocol {
func curve25519Base64() async -> String? { func curve25519Base64() async -> String? {
await client.encryption().curve25519Key() await client.encryption().curve25519Key()
} }
func resetIdentity() async -> Result<IdentityResetHandle?, ClientProxyError> {
do {
return try await .success(client.encryption().resetIdentity())
} catch {
return .failure(.sdkError(error))
}
}
} }
extension ClientProxy: MediaLoaderProtocol { extension ClientProxy: MediaLoaderProtocol {
@@ -190,8 +190,10 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
func recentConversationCounterparts() async -> [UserProfileProxy] func recentConversationCounterparts() async -> [UserProfileProxy]
// MARK: - Encryption Info // MARK: - Crypto
func ed25519Base64() async -> String? func ed25519Base64() async -> String?
func curve25519Base64() async -> String? func curve25519Base64() async -> String?
func resetIdentity() async -> Result<IdentityResetHandle?, ClientProxyError>
} }
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2f21a974ffbabece1a0bf4761e6307c096382fec58c56eb9e6313a2453a1be07 oid sha256:1c2db75b98f86afcffbba913ef8d728d6a6ab51d3b73314897c1108210d00c45
size 515653 size 517693
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2904bd34a9ebd5113aed2fe521a91f552648270a0ecce950353f167dd4306a0d oid sha256:87469d91baa3ee639d04012ad9afcf049eb8e9c6cd78fb6dadbac5fbcfb481f3
size 541329 size 543421
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c69e5671c7d50cd1b49590e9daae7ea286ecddde1e88f89181ad48c2456e73d2 oid sha256:c8f77a8e5c48eb636514ce6f735c79d583c4ffc7b034cdc49484fbff0ec4a882
size 314645 size 315619
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ff8d146eef1c077b5a1eedb7e6872248ea07c06995f443ab3282a10c8e9181d3 oid sha256:e0f75923ed4fcfb1c774751abe0a5697fbbf71a274a163dce56c1723a1e6ead2
size 319983 size 321695
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:a0c76b4c51a368ac5c5bfa4f37355bbfb7f9f8a62f3f97a9b4aead814ed0d242 oid sha256:3f008b0b91873db9b4102bf8508a78372db9440f577c609e1677837e19561dbb
size 114226 size 111069
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9beba313e377cdf2d2910d576a1f450fa5e1e999c25a5062b663a8b22a45d0cc oid sha256:668a9c0536b5155b7bf07e6b8fc7de64e94c15868d5efee11cdb771d9cf2175d
size 119634 size 118743
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:20b5be056145918d911a4139b45f46edd1e4a53445e9f75a977dddec3f5da62e oid sha256:82b98dbc5b90e4f3432d4d311cf98b1f8762e22b7b4437364030633782145f38
size 76034 size 73447
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b42bce7f01ea1be7410870009a4cb7b80b8ef7fe011cd4bd631b610a530645a2 oid sha256:3701ce1293f61e7b35abfe35d13f5860c1a87136ecaa3d3406e8d0dd117a6b14
size 90993 size 87369
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97f681fac8805300e66945b3b597b55cf79dbe10aa3aca33a3f3405f981ae3bd
size 98889
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:614d8e886f6bd587cadaf1133a96647ede185615cf6fe4b33a75e9138f7b475c
size 113456
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c869098036009618cfd8f5e6491be8f3af6c92d60c2e8d3edc158767a671dfd1
size 57235
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4cd756e4bb99afbc90d2fb50fa17c766412698c768d915bd3ee828d5564f38ba
size 73637
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e125593fee18c805f9a4e44737266b17fb7673160a1da100b5b9379e6e3cb50b
size 168133
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:434146f53746a7a1bffd6483f3eb47e79bf38b1cbce86de68921391c42ac6817
size 238287
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:315e9644456d7221df9953dc73ec9158fb2eaa0427898155c5d79066ba7ee0ee
size 124373
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:93549b9921c66b937a191ff6e6dccd49f76cafb7f1e62053d1c2b4fa53d5f7b1
size 164940
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c94b4d8994a63360474b918a7461b406107e327c2cf18809f1d211da7e5f1f81 oid sha256:bf60b748aa8c48aad659c3567c814cc1f601c194fbafcfffeed37fe6f3594e40
size 92000 size 108900
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5bd6f0eff9279d3fedceb20af31fd32c70553c5bed46fad1c2ebcecfd171017a oid sha256:080f9960d7ca7e83a183050cc663c50635a7a6260bcfd808cf7607680cbf7ae4
size 100481 size 123013
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9a204e019bcac509fd8a24e31d9f7b0c35aac8e3c29aae90ebf89907fbf9a4f9 oid sha256:797ad10083353eeb2362f882ff1072a213dde5c879511e5854c4aa415f68d35e
size 49920 size 64174
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:12573f8390f7371d346962d7d411b617a701028052e828c4c8158d530bc40bdc oid sha256:e0d54f1544f9cd0ffc14183a8baff1317fd0c793ca94c7e88e8a0a2d02816b36
size 66502 size 81854
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3e84dbf93c9139a5bb20863137b2736db81fb356298cb207b35da3313ed2b3c6
size 142887
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:baab0084096811ea0d2aecb19ac51abf64fc286bc4299506686b79350acf19f6
size 183006
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:edbce917e9bce0e4dd1f64c88b8c15b7e8a08975470e4b01c7f121ae27d3252e
size 98702
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8da5536587856a1c615648e238a45638b41957784c6c3981359d9bfb1cea5995
size 148117
+1 -1
View File
@@ -60,7 +60,7 @@ packages:
# Element/Matrix dependencies # Element/Matrix dependencies
MatrixRustSDK: MatrixRustSDK:
url: https://github.com/element-hq/matrix-rust-components-swift url: https://github.com/element-hq/matrix-rust-components-swift
exactVersion: 1.0.29 exactVersion: 1.0.30
# path: ../matrix-rust-sdk # path: ../matrix-rust-sdk
Compound: Compound:
url: https://github.com/element-hq/compound-ios url: https://github.com/element-hq/compound-ios