In preparation of FTUE changes... (#2556)

* Remove the welcome screen

* Allow the UserSessionFlowCoordinator to control the whole app hierarchy, not only its splitView

* Start using the new verification state listener

* Rename Onboarding to AuthenticationStart in preparation for the new OnboardingFlowCoordinator; update snapshots and tests

* Make the AuthenticationCoordinator a proper FlowCoordinator

* Add some padding around the authentication start screen report a problem button

* Bump the RustSDK to v1.1.49

* Only add bottom padding on the authentication start screen report a problem button
This commit is contained in:
Stefan Ceriu 2024-03-13 11:24:48 +02:00 committed by GitHub
parent d7e0bbc537
commit 5944550721
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 277 additions and 754 deletions

View File

@ -63,7 +63,6 @@
0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */; };
0BE4D5CBF86956410F071F91 /* CreateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */; };
0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */; };
0C26A1588B17DCDE5F490FE3 /* OnboardingScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53D6BB7E8E5EC031281872C /* OnboardingScreenViewModelTests.swift */; };
0C47AE2CA7929CB3B0E2D793 /* ServerSelectionScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0685156EB62D7E243F097CFC /* ServerSelectionScreenViewModelProtocol.swift */; };
0C58A846F61949B1D545D661 /* NoticeRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */; };
0C797CD650DFD2876BEC5173 /* CollapsibleReactionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */; };
@ -73,6 +72,7 @@
0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */; };
0DCDF49AB95F75BFC8B1879C /* SwipeToReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E45C3DC740D3AB9A47FD32 /* SwipeToReplyView.swift */; };
0E08BB72B2258652CF501A8B /* Prefire in Frameworks */ = {isa = PBXBuildFile; productRef = 9B68DE8678BF67D4612BCC16 /* Prefire */; };
0E3A2787C6AEC761A81A938A /* AuthenticationStartScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */; };
0E8C480700870BB34A2A360F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4003BC24B24C9E63D3304177 /* DeviceKit */; };
0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
0ED691ADC9C2EA457E7A9427 /* FormattingToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE449DFBA7CC863EEB2FD2A /* FormattingToolbar.swift */; };
@ -138,7 +138,6 @@
208C19811613F9A10F8A7B75 /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; };
20C16A3F718802B0E4A19C83 /* URLComponentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76310030C831D4610A705603 /* URLComponentsTests.swift */; };
21813AF91CFC6F3E3896DB53 /* AppLockSetupBiometricsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */; };
2185C1F6724C78FFF355D6FA /* WelcomeScreenScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB10FA6570DD08B3966C159 /* WelcomeScreenScreenUITests.swift */; };
21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */; };
21BF2B7CEDFE3CA67C5355AD /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = C733D11B421CFE3A657EF230 /* test_image.png */; };
21F29351EDD7B2A5534EE862 /* SecureBackupKeyBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */; };
@ -174,6 +173,7 @@
29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; };
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
29EE1791E0AFA1ABB7F23D2F /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */; };
2A90DD14DE5C891BFA433950 /* TimelineReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */; };
2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */; };
2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */; };
@ -229,7 +229,6 @@
377980ABF16525114E72DDE2 /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = 2B9ACE4FCACB5A8812154424 /* Version */; };
37906355E207DB5703754675 /* AppLockSetupBiometricsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9F893F4A111CB7BA5C96949 /* AppLockSetupBiometricsScreenViewModel.swift */; };
37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */; };
383055C6ABE5BE058CEE1DDB /* WelcomeScreenScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57FE5EF0AFFE360C66420AAE /* WelcomeScreenScreenCoordinator.swift */; };
384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */; };
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */; };
@ -240,7 +239,6 @@
39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */; };
3A08584ECDD4A4541DBF21F8 /* EmojiLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */; };
3A164187907DA43B7858F9EC /* CompletionSuggestionServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA0312A6262484AA393AC9 /* CompletionSuggestionServiceTests.swift */; };
3A5BD701D1AC916AC534F52C /* OnboardingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB26F24164E9461B2054D0B3 /* OnboardingScreenModels.swift */; };
3A64A93A651A3CB8774ADE8E /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = BA93CD75CCE486660C9040BD /* Collections */; };
3A7DD0D13B0FB8876D69D829 /* TextBasedRoomTimelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */; };
3B0F9B57D25B07E66F15762A /* MediaUploadPreviewScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */; };
@ -288,8 +286,8 @@
46A6DB0F78FB399BD59E2D41 /* EncryptionKeyProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */; };
46BA7F4B4D3A7164DED44B88 /* FullscreenDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 565F1B2B300597C616B37888 /* FullscreenDialog.swift */; };
46C9F8FE3810A04A005FE16B /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B19B2BCC779ED934E0BBC2A /* AudioPlayer.swift */; };
4714991754A08B58B4D7ED85 /* OnboardingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F27BAB69EB568369F1F6B3 /* OnboardingScreenViewModelProtocol.swift */; };
47305C0911C9E1AA774A4000 /* TemplateScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */; };
47597438020EC8144E535425 /* AuthenticationStartScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D1294D5DC41A40CD3C8D46 /* AuthenticationStartScreenUITests.swift */; };
4799A852132F1744E2825994 /* CreateRoomViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */; };
47FF70C051A991FB65CDBCF3 /* RoomScreenInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0135A608FFAD86E6674EE730 /* RoomScreenInteractionHandler.swift */; };
4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */; };
@ -414,6 +412,7 @@
6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */; };
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; };
67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */; };
6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */; };
68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; };
6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
@ -474,7 +473,6 @@
7691233E3572A9173FD96CB3 /* SecureBackupKeyBackupScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */; };
76BA28216FBAF83B2D86A027 /* InvitesScreenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2A71915C1F075E403F559C /* InvitesScreenCell.swift */; };
7708976CEE6AFB5CFAEFBA68 /* PillTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */; };
7719778A682FDAC21445E9C8 /* OnboardingLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0D7955FFB19B584594844B /* OnboardingLogo.swift */; };
7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; };
77693820498ABF3508814D49 /* AppLockServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */; };
77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; };
@ -488,6 +486,7 @@
79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */; };
7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */; };
7A0A0929556792FB19B812C5 /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84816E0D2F34E368BF64FA60 /* SessionVerificationScreen.swift */; };
7A170A5A4A352954BB2A1B96 /* AuthenticationStartScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */; };
7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; };
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
7AEC56ADEFC5A7198A17412F /* InviteUsersScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADB35E2DB4EFE8E6F3959629 /* InviteUsersScreenUITests.swift */; };
@ -499,17 +498,14 @@
7C384A8E54A4B60A14CDE8E5 /* WaitlistScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */; };
7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; };
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; };
7CFCC177F0ED083867FAD9C9 /* OnboardingScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E727F7E0BCE8A0BBFD33FF /* OnboardingScreenCoordinator.swift */; };
7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */; };
7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; };
7D6DC832DE7A3DE874E2E9BC /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */; };
7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; };
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; };
7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; };
7F02063FB3D1C3E5601471A1 /* WelcomeScreenScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851EF6258DF8B7EF129DC3AC /* WelcomeScreenScreenViewModelTests.swift */; };
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; };
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */; };
7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */; };
7F941B063C94E1718DFC2CF3 /* RoomChangeRolesScreenRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E6EB7960BC9D0F7396B3BD /* RoomChangeRolesScreenRow.swift */; };
7FB0BDE26838F1A92782D5E1 /* MediaUploadPreviewScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */; };
@ -550,6 +546,7 @@
8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */; };
872A6457DF573AF8CEAE927A /* LoginHomeserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */; };
874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */; };
878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; };
87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */; };
87CEDB8A0696F0D5AE2ABB28 /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = D5E26C54362206BBDD096D83 /* test_audio.mp3 */; };
@ -582,6 +579,7 @@
8DCD9CC5361FF22A5B2C20F1 /* AppLockSetupSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9FCE4D1E3A81AC1CC5CB91 /* AppLockSetupSettingsScreenCoordinator.swift */; };
8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */; };
8E650379587C31D7912ED67B /* UNNotification+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */; };
8ED8AF57A06F5EE9978ED23F /* AuthenticationStartScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */; };
8EF63DDDC1B54F122070B04D /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */; };
8F2FAA98457750D9D664136F /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; };
90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE40D4A5DD857AC16EED945A /* URLSession.swift */; };
@ -590,7 +588,6 @@
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; };
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
92133B170A1F917685E9FF78 /* OnboardingScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */; };
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
92720AB0DA9AB5EEF1DAF56B /* SecureBackupLogoutConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DC017C3CB6B0F7C63F460F2 /* SecureBackupLogoutConfirmationScreenViewModel.swift */; };
9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */; };
@ -603,7 +600,6 @@
9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */; };
9462C62798F47E39DCC182D2 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA89A2DD51B6BBE1DA55E263 /* Application.swift */; };
94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */; };
94CEF587A3994A36A46D8334 /* WelcomeScreenScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7101698791B321A76F552804 /* WelcomeScreenScreenViewModelProtocol.swift */; };
94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
95690DDD9D547D3D842ACBE3 /* AnalyticsSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */; };
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */; };
@ -633,6 +629,7 @@
9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */; };
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9BEA56957B3AF954E7321658 /* ComposerToolbarViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E44928D844E16EE48A311FCA /* ComposerToolbarViewModelProtocol.swift */; };
9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; };
9C5A07E7C33F3F40287D7861 /* SettingsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */; };
9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; };
9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; };
@ -672,12 +669,12 @@
A439B456D0761D6541745CC3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; };
A440D4BC02088482EC633A88 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; };
A494741843F087881299ACF0 /* RestorationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3558A15CFB934F9229301527 /* RestorationToken.swift */; };
A4AF12D9D8BA34B3B7B55B08 /* AuthenticationStartScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */; };
A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */; };
A4B123C635F70DDD4BC2FAC9 /* BlockedUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */; };
A4C29D373986AFE4559696D5 /* SecureBackupKeyBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */; };
A4E885358D7DD5A072A06824 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = CCE5BF78B125320CBF3BB834 /* PostHog */; };
A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */; };
A5C5C18671EDD2747AC16D2D /* OnboardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49C1CEBA9BCF5D2AD1884FA /* OnboardingScreenViewModel.swift */; };
A5D551E5691749066E0E0C44 /* RoomDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */; };
A64B52D9F73F9A6B95AF24FE /* UserDetailsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */; };
A680F54935A6ADEA4ED6C38F /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A4C9547BBFEEF30AA11329B /* TimelineItemStatusView.swift */; };
@ -709,7 +706,6 @@
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; };
AC7AA215D60FBC307F984028 /* Consumable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127A57D053CE8C87B5EFB089 /* Consumable.swift */; };
AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */; };
ACF094CF3BF02DBFA6DFDE60 /* AuthenticationCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */; };
AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; };
AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */; };
AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */; };
@ -781,7 +777,6 @@
BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; };
BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */; };
BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */; };
BD2BF1EC73FFB0C01552ECDA /* WelcomeScreenScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */; };
BD6685592716CA957D7BAAC4 /* RoomChangeRolesScreenSelectedItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */; };
BD6D98676111DA8FC2BE4908 /* InvitesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86873A768B13069BB5CAECF6 /* InvitesScreenViewModelProtocol.swift */; };
BD782053BE4C3D2F0BDE5699 /* ServiceLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */; };
@ -793,7 +788,6 @@
C0090506A52A1991BAF4BA68 /* NotificationSettingsChatType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */; };
C051475DFF4C8EBDDF4DC8E4 /* StartChatScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */; };
C08AAE7563E0722C9383F51C /* RoomMembersListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */; };
C0DC02E2B91DC76A4D1A0E7F /* OnboardingScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F3450F4C32D73532DBBC1A2 /* OnboardingScreenBackgroundImage.swift */; };
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */; };
C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */; };
C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */; };
@ -891,7 +885,6 @@
D7CDBAE82782BD0529DECB5F /* AttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */; };
D8359F67AF3A83516E9083C1 /* MockUserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4756C5A8C8649AD6C10C615 /* MockUserSession.swift */; };
D8385A51A3D0FA9283556281 /* RoundedLabelItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745323FCF9AF21A117252C53 /* RoundedLabelItem.swift */; };
D871C8CF46950F959C9A62C3 /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54464351F170D570110AFCA /* WelcomeScreen.swift */; };
D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; };
D9473FC9B077A6EDB7A12001 /* LocationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */; };
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
@ -900,7 +893,6 @@
DB079D1929B5A5F52D207C83 /* RoomDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */; };
DBC8D1DBFE9F9CA7662BC8AA /* RoomPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */; };
DC08ADC41E792086A340A8B3 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
DC1BB5EE5F4D9B6A1F98A77A /* WelcomeScreenScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC2E8E1B20BB2EA07B0B61E /* WelcomeScreenScreenViewModel.swift */; };
DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */; };
DC77E9DB2CFBE84A2BDF20C5 /* RoomRolesAndPermissionsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */; };
DDB47D29C6865669288BF87C /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; };
@ -936,6 +928,7 @@
E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */; };
E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */; };
E4BAEED438A843D7B01D8069 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */; };
E4F924DECC66389C1C810550 /* AuthenticationStartScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */; };
E570117376826665640F0CFD /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */; };
E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */; };
E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */; };
@ -946,6 +939,7 @@
E77FE06B165A38BF1735509F /* SecureBackupScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF73F49E6B6683F7E2D26F0 /* SecureBackupScreenCoordinator.swift */; };
E78D429F18071545BF661A52 /* RoomDetailsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */; };
E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */; };
E79B247A6DD28759636317EA /* AuthenticationStartScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */; };
E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; };
E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; };
E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; };
@ -955,7 +949,6 @@
E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; };
E9F148072F9513EC2272AA21 /* SessionVerificationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A96A67AD0E32C48941EFBB3 /* SessionVerificationScreenCoordinator.swift */; };
EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; };
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */; };
EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; };
EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; };
EA974337FA7D040E7C74FE6E /* RoomDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */; };
@ -1168,7 +1161,6 @@
0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenModels.swift; sourceTree = "<group>"; };
0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenCoordinator.swift; sourceTree = "<group>"; };
0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenModels.swift; sourceTree = "<group>"; };
105429F29096729EDD3152CF /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SAS.strings; sourceTree = "<group>"; };
1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
@ -1261,6 +1253,7 @@
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = "<group>"; };
24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreen.swift; sourceTree = "<group>"; };
24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreen.swift; sourceTree = "<group>"; };
24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterView.swift; sourceTree = "<group>"; };
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
2525D78FEA7E7B132ED85C58 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -1282,6 +1275,7 @@
283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheTests.swift; sourceTree = "<group>"; };
287FC98AF2664EAD79C0D902 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItemContent.swift; sourceTree = "<group>"; };
295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinatorUITests.swift; sourceTree = "<group>"; };
2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilder.swift; sourceTree = "<group>"; };
2A96A67AD0E32C48941EFBB3 /* SessionVerificationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenCoordinator.swift; sourceTree = "<group>"; };
2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineTests.swift; sourceTree = "<group>"; };
@ -1329,7 +1323,6 @@
37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiItem.swift; sourceTree = "<group>"; };
37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; };
37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringTests.swift; sourceTree = "<group>"; };
37E727F7E0BCE8A0BBFD33FF /* OnboardingScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenCoordinator.swift; sourceTree = "<group>"; };
37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreen.swift; sourceTree = "<group>"; };
382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxyMock.swift; sourceTree = "<group>"; };
38345442415E07A931197C55 /* AppLockScreenPINKeypad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenPINKeypad.swift; sourceTree = "<group>"; };
@ -1428,6 +1421,7 @@
502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenModels.swift; sourceTree = "<group>"; };
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = "<group>"; };
50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenBackgroundImage.swift; sourceTree = "<group>"; };
50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixUserShareLink.swift; sourceTree = "<group>"; };
50F23B21CF15F9F4BAA0788B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
@ -1457,7 +1451,6 @@
57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConsentState.swift; sourceTree = "<group>"; };
57EAAF82432B0B53881CF826 /* AudioRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItem.swift; sourceTree = "<group>"; };
57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLocator.swift; sourceTree = "<group>"; };
57FE5EF0AFFE360C66420AAE /* WelcomeScreenScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenCoordinator.swift; sourceTree = "<group>"; };
584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.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>"; };
@ -1465,16 +1458,15 @@
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; };
596AA8843AC1A234F3387767 /* SecureBackupRecoveryKeyScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenCoordinator.swift; sourceTree = "<group>"; };
59846FA04E1DBBFDD8829C2A /* MessageForwardingScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenUITests.swift; sourceTree = "<group>"; };
598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartLogo.swift; sourceTree = "<group>"; };
5A07692536D66E3DA32C4964 /* LogViewerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreen.swift; sourceTree = "<group>"; };
5A1119E9C63AE530252640D2 /* SecureBackupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupController.swift; sourceTree = "<group>"; };
5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreen.swift; sourceTree = "<group>"; };
5A37E2FACFD041CE466223CD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenCoordinator.swift; sourceTree = "<group>"; };
5B0D7955FFB19B584594844B /* OnboardingLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingLogo.swift; sourceTree = "<group>"; };
5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = "<group>"; };
5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = "<group>"; };
5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = "<group>"; };
5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinatorUITests.swift; sourceTree = "<group>"; };
5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledFrameModifier.swift; sourceTree = "<group>"; };
5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiDetection.swift; sourceTree = "<group>"; };
5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProperties.swift; sourceTree = "<group>"; };
@ -1504,6 +1496,7 @@
65AAD845E53B0C8B5E0812C2 /* UserDiscoveryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryService.swift; sourceTree = "<group>"; };
65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthenticationServiceProxy.swift; sourceTree = "<group>"; };
6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenCoordinator.swift; sourceTree = "<group>"; };
667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenUITests.swift; sourceTree = "<group>"; };
669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = "<group>"; };
@ -1541,7 +1534,6 @@
7023EB4F3B7C7D1FBA68638B /* TimelineItemDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemDebugView.swift; sourceTree = "<group>"; };
7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModel.swift; sourceTree = "<group>"; };
70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreen.swift; sourceTree = "<group>"; };
7101698791B321A76F552804 /* WelcomeScreenScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenViewModelProtocol.swift; sourceTree = "<group>"; };
713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenViewModelProtocol.swift; sourceTree = "<group>"; };
71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
7199693797B66245EF97BCF5 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -1617,10 +1609,10 @@
84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpiringTaskRunnerTests.swift; sourceTree = "<group>"; };
85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenViewModelProtocol.swift; sourceTree = "<group>"; };
851B95BB98649B8E773D6790 /* AppLockService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockService.swift; sourceTree = "<group>"; };
851EF6258DF8B7EF129DC3AC /* WelcomeScreenScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenViewModelTests.swift; sourceTree = "<group>"; };
8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelTests.swift; sourceTree = "<group>"; };
854BCEAF2A832176FAACD2CB /* SplashScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenCoordinator.swift; sourceTree = "<group>"; };
85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenModels.swift; sourceTree = "<group>"; };
8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
86376BEE425704AEE197CA54 /* PillContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillContext.swift; sourceTree = "<group>"; };
8642512079EEFD622E3AA66B /* BlockedUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenModels.swift; sourceTree = "<group>"; };
@ -1636,7 +1628,6 @@
8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
897DF5E9A70CE05A632FC8AF /* UTType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTType.swift; sourceTree = "<group>"; };
89AAEA70CFF3284920811941 /* RoomChangePermissionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreen.swift; sourceTree = "<group>"; };
8AB10FA6570DD08B3966C159 /* WelcomeScreenScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenUITests.swift; sourceTree = "<group>"; };
8AE0C9653870803E4F91F474 /* RoomListFiltersStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersStateTests.swift; sourceTree = "<group>"; };
8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainMentionBuilder.swift; sourceTree = "<group>"; };
8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoader.swift; sourceTree = "<group>"; };
@ -1644,7 +1635,6 @@
8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenCoordinator.swift; sourceTree = "<group>"; };
8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItemContent.swift; sourceTree = "<group>"; };
8CC23C63849452BC86EA2852 /* ButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyle.swift; sourceTree = "<group>"; };
8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenUITests.swift; sourceTree = "<group>"; };
8D1FA20DAB853C1156054912 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = "<group>"; };
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -1656,6 +1646,7 @@
8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionView.swift; sourceTree = "<group>"; };
8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenUITests.swift; sourceTree = "<group>"; };
8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = "<group>"; };
8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelTests.swift; sourceTree = "<group>"; };
8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
90791B9C739C716A40E1B230 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
907FA4DE17DEA1A3738EFB83 /* AudioRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorder.swift; sourceTree = "<group>"; };
@ -1697,6 +1688,7 @@
9B65A314DF40B6BBF775C2BC /* AnalyticsPromptScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenCoordinator.swift; sourceTree = "<group>"; };
9B663BE498BB39EADC24025D /* SettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenModels.swift; sourceTree = "<group>"; };
9B7D8D3638864B7482E148CC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; };
9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModel.swift; sourceTree = "<group>"; };
9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestMeasurementParser.swift; sourceTree = "<group>"; };
9C5E81214D27A6B898FC397D /* ElementX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = "<group>"; };
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = "<group>"; };
@ -1704,7 +1696,6 @@
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachment.swift; sourceTree = "<group>"; };
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; };
9F3450F4C32D73532DBBC1A2 /* OnboardingScreenBackgroundImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenBackgroundImage.swift; sourceTree = "<group>"; };
9F40FB0A43DAECEC27C73722 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/SAS.strings; sourceTree = "<group>"; };
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
9FB4F169D653296023ED65E6 /* NSESettingsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESettingsProtocol.swift; sourceTree = "<group>"; };
@ -1739,6 +1730,7 @@
A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = "<group>"; };
A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = "<group>"; };
A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = "<group>"; };
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinator.swift; sourceTree = "<group>"; };
A9FAFE1C2149E6AC8156ED2B /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = "<group>"; };
AA19C32BD97F45847724E09A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Untranslated.strings; sourceTree = "<group>"; };
AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1746,7 +1738,6 @@
AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserProfile+Mock.swift"; sourceTree = "<group>"; };
AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationAnnotation.swift; sourceTree = "<group>"; };
AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskServiceProtocol.swift; sourceTree = "<group>"; };
AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreen.swift; sourceTree = "<group>"; };
ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelTests.swift; sourceTree = "<group>"; };
AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = "<group>"; };
@ -1823,6 +1814,7 @@
B902EA6CD3296B0E10EE432B /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = "<group>"; };
B9227F7495DA43324050A863 /* TextBasedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineItem.swift; sourceTree = "<group>"; };
B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenModels.swift; sourceTree = "<group>"; };
B9D1294D5DC41A40CD3C8D46 /* AuthenticationStartScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenUITests.swift; sourceTree = "<group>"; };
BA188BB0A216D763E46E3279 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = "<group>"; };
BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreferenceTests.swift; sourceTree = "<group>"; };
BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenModels.swift; sourceTree = "<group>"; };
@ -1859,10 +1851,8 @@
C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKGeneratedMocks.swift; sourceTree = "<group>"; };
C352359663A0E52BA20761EE /* LoadableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableImage.swift; sourceTree = "<group>"; };
C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManagerProtocol.swift; sourceTree = "<group>"; };
C49C1CEBA9BCF5D2AD1884FA /* OnboardingScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenViewModel.swift; sourceTree = "<group>"; };
C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelProtocol.swift; sourceTree = "<group>"; };
C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
C54464351F170D570110AFCA /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
C55679AF67545EF8087E47BE /* RoomMemberDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetails.swift; sourceTree = "<group>"; };
C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderStateTests.swift; sourceTree = "<group>"; };
C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxy.swift; sourceTree = "<group>"; };
@ -1895,7 +1885,6 @@
CA90BD288E5AE6BC643AFDDF /* TemplateScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenCoordinator.swift; sourceTree = "<group>"; };
CACA846B3E3E9A521D98B178 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModelTests.swift; sourceTree = "<group>"; };
CB26F24164E9461B2054D0B3 /* OnboardingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenModels.swift; sourceTree = "<group>"; };
CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillConstants.swift; sourceTree = "<group>"; };
CBBCC6E74774E79B599625D0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = "<group>"; };
@ -1941,7 +1930,6 @@
D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; };
D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineItem.swift; sourceTree = "<group>"; };
D53D6BB7E8E5EC031281872C /* OnboardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenViewModelTests.swift; sourceTree = "<group>"; };
D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelProtocol.swift; sourceTree = "<group>"; };
D5AC06FC11B6638F7BF1670E /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = "<group>"; };
D5E26C54362206BBDD096D83 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = "<group>"; };
@ -1949,7 +1937,6 @@
D622EC7898469BB1D0881CDD /* PollFormScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreen.swift; sourceTree = "<group>"; };
D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenCoordinator.swift; sourceTree = "<group>"; };
D66B5D86A9AB95E0E01BED82 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = "<group>"; };
D6DC38E64A5ED3FDB201029A /* BugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportService.swift; sourceTree = "<group>"; };
D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConfiguration.swift; sourceTree = "<group>"; };
D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@ -1977,6 +1964,7 @@
DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineItem.swift; sourceTree = "<group>"; };
E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerAuthorization.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>"; };
E0FCA0957FAA0E15A9F5579D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Untranslated.stringsdict; 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>"; };
@ -1986,7 +1974,6 @@
E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledPaddingModifier.swift; sourceTree = "<group>"; };
E2B1CC9AA154F4D5435BF60A /* Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = "<group>"; };
E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = "<group>"; };
E2F27BAB69EB568369F1F6B3 /* OnboardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenViewModelProtocol.swift; sourceTree = "<group>"; };
E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxyMock.swift; sourceTree = "<group>"; };
E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModel.swift; sourceTree = "<group>"; };
E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = "<group>"; };
@ -2095,7 +2082,6 @@
FDBA358C79F0DCBC4FA14A88 /* SecureBackupRecoveryKeyScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenUITests.swift; sourceTree = "<group>"; };
FDF73F49E6B6683F7E2D26F0 /* SecureBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenCoordinator.swift; sourceTree = "<group>"; };
FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProtocol.swift; sourceTree = "<group>"; };
FEC2E8E1B20BB2EA07B0B61E /* WelcomeScreenScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenViewModel.swift; sourceTree = "<group>"; };
FFECCE59967018204876D0A5 /* LocationMarkerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationMarkerView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -2532,6 +2518,18 @@
path = ComposerToolbar;
sourceTree = "<group>";
};
295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */ = {
isa = PBXGroup;
children = (
6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */,
8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */,
9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */,
E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */,
F3F90EBF3341F1FB47579B77 /* View */,
);
path = AuthenticationStartScreen;
sourceTree = "<group>";
};
2AC6FD695C6F79F67C056463 /* AppLockSetupSettingsScreen */ = {
isa = PBXGroup;
children = (
@ -2845,18 +2843,6 @@
path = Fixtures;
sourceTree = "<group>";
};
3F38EAC92E2281990E65DAF2 /* OnboardingScreen */ = {
isa = PBXGroup;
children = (
37E727F7E0BCE8A0BBFD33FF /* OnboardingScreenCoordinator.swift */,
CB26F24164E9461B2054D0B3 /* OnboardingScreenModels.swift */,
C49C1CEBA9BCF5D2AD1884FA /* OnboardingScreenViewModel.swift */,
E2F27BAB69EB568369F1F6B3 /* OnboardingScreenViewModelProtocol.swift */,
7B14834450AE76EEFDDBCBB8 /* View */,
);
path = OnboardingScreen;
sourceTree = "<group>";
};
3FDB9ADD4A6456674E748166 /* SupportingFiles */ = {
isa = PBXGroup;
children = (
@ -3169,6 +3155,7 @@
children = (
FCE93F0CBF0D96B77111C413 /* AppLockFlowCoordinator.swift */,
0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */,
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */,
7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */,
9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */,
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */,
@ -3438,6 +3425,7 @@
89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */,
C55CC239AE12339C565F6C9A /* AudioRecorderStateTests.swift */,
2441E2424E78A40FC95DBA76 /* AudioRecorderTests.swift */,
8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */,
6DFCAA239095A116976E32C4 /* BackgroundTaskTests.swift */,
240610DF32F3213BEC5611D7 /* BlockedUsersScreenViewModelTests.swift */,
EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */,
@ -3473,7 +3461,6 @@
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */,
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */,
D53D6BB7E8E5EC031281872C /* OnboardingScreenViewModelTests.swift */,
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */,
31A6314FDC51DA25712D9A81 /* PillContextTests.swift */,
347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */,
@ -3516,7 +3503,6 @@
AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */,
D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */,
C796FC1DFDBCDD5573D0360F /* WaitlistScreenViewModelTests.swift */,
851EF6258DF8B7EF129DC3AC /* WelcomeScreenScreenViewModelTests.swift */,
53280D2292E6C9C7821773FD /* UserSession */,
9613851C68D8C01EABFB3569 /* AppLock */,
70C5B842301AC281DF374E41 /* Extensions */,
@ -3679,16 +3665,6 @@
path = View;
sourceTree = "<group>";
};
7B14834450AE76EEFDDBCBB8 /* View */ = {
isa = PBXGroup;
children = (
5B0D7955FFB19B584594844B /* OnboardingLogo.swift */,
AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */,
9F3450F4C32D73532DBBC1A2 /* OnboardingScreenBackgroundImage.swift */,
);
path = View;
sourceTree = "<group>";
};
7B890CCD20B037760BFDF957 /* RoomRolesAndPermissionsScreen */ = {
isa = PBXGroup;
children = (
@ -3926,18 +3902,6 @@
path = ElementCall;
sourceTree = "<group>";
};
93F4D089C78719B688D576ED /* WelcomeScreenScreen */ = {
isa = PBXGroup;
children = (
57FE5EF0AFFE360C66420AAE /* WelcomeScreenScreenCoordinator.swift */,
0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */,
FEC2E8E1B20BB2EA07B0B61E /* WelcomeScreenScreenViewModel.swift */,
7101698791B321A76F552804 /* WelcomeScreenScreenViewModelProtocol.swift */,
C5B85A56479F1382EA5A9913 /* View */,
);
path = WelcomeScreenScreen;
sourceTree = "<group>";
};
948DD12A5533BE1BC260E437 /* LocationSharing */ = {
isa = PBXGroup;
children = (
@ -3968,7 +3932,8 @@
7D0CBC76C80E04345E11F2DB /* Application.swift */,
E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */,
F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */,
5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */,
295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */,
B9D1294D5DC41A40CD3C8D46 /* AuthenticationStartScreenUITests.swift */,
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */,
1D8866FE1CCCF10305FCACBC /* CallScreenUITests.swift */,
F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */,
@ -3982,7 +3947,6 @@
59846FA04E1DBBFDD8829C2A /* MessageForwardingScreenUITests.swift */,
46F52419AEEDA2C006CB7181 /* NotificationSettingsEditScreenUITests.swift */,
B83BC0DC9A2DF2DD60F9B6E9 /* NotificationSettingsScreenUITests.swift */,
8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */,
3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */,
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */,
122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */,
@ -4005,7 +3969,6 @@
DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */,
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */,
ECB08484CD5D77C9BF97AA78 /* WaitlistScreenUITests.swift */,
8AB10FA6570DD08B3966C159 /* WelcomeScreenScreenUITests.swift */,
);
path = Sources;
sourceTree = "<group>";
@ -4528,14 +4491,6 @@
path = CreateRoom;
sourceTree = "<group>";
};
C5B85A56479F1382EA5A9913 /* View */ = {
isa = PBXGroup;
children = (
C54464351F170D570110AFCA /* WelcomeScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
CA15BB3F6C62B35AE2C281A9 /* Provider */ = {
isa = PBXGroup;
children = (
@ -4740,6 +4695,7 @@
669239C03835CD8B51E0FFDB /* AnalyticsPromptScreen */,
13263FFEA7749D822B51AA90 /* AppLock */,
E74CD7681375AD2EAA34D66B /* Authentication */,
295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */,
EFD4F7FCAAAB3EF45EE7A067 /* BlockedUsersScreen */,
53FB148CD26AFB6A5B9E20B3 /* BugReportScreen */,
1185EECDD07495D65AC84AFC /* CallScreen */,
@ -4757,7 +4713,6 @@
87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */,
23605DD08620BE6558242469 /* MediaUploadPreviewScreen */,
3348D14DBDB54E72FC67E2F3 /* MessageForwardingScreen */,
3F38EAC92E2281990E65DAF2 /* OnboardingScreen */,
A448A3A8F764174C60CD0CA1 /* Other */,
5970F275D6014548DCED6106 /* ReportContentScreen */,
DAB7DC51866A6D1B51BDC3A2 /* RoomChangePermissionsScreen */,
@ -4774,7 +4729,6 @@
3153FCA3F4B0E88B16D99D12 /* SessionVerificationScreen */,
70B74A432C241E56A7ACE610 /* Settings */,
EC4545C7E37E8294D3FE6800 /* StartChatScreen */,
93F4D089C78719B688D576ED /* WelcomeScreenScreen */,
);
path = Screens;
sourceTree = "<group>";
@ -4838,7 +4792,6 @@
E74CD7681375AD2EAA34D66B /* Authentication */ = {
isa = PBXGroup;
children = (
D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */,
CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */,
92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */,
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */,
@ -4915,6 +4868,16 @@
path = InviteUsersScreen;
sourceTree = "<group>";
};
F3F90EBF3341F1FB47579B77 /* View */ = {
isa = PBXGroup;
children = (
598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */,
24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */,
50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */,
);
path = View;
sourceTree = "<group>";
};
F49710373735A3B8BB76DFF7 /* View */ = {
isa = PBXGroup;
children = (
@ -5524,6 +5487,7 @@
C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */,
3042527CB344A9EF1157FC26 /* AudioRecorderStateTests.swift in Sources */,
192A3CDCD0174AD1E4A128E4 /* AudioRecorderTests.swift in Sources */,
8ED8AF57A06F5EE9978ED23F /* AuthenticationStartScreenViewModelTests.swift in Sources */,
0F9E38A75337D0146652ACAB /* BackgroundTaskTests.swift in Sources */,
CEAEA57B7665C8E790599A78 /* BlockedUsersScreenViewModelTests.swift in Sources */,
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */,
@ -5569,7 +5533,6 @@
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */,
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */,
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */,
0C26A1588B17DCDE5F490FE3 /* OnboardingScreenViewModelTests.swift in Sources */,
50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */,
27E9263DA75E266690A37EB1 /* PermalinkBuilderTests.swift in Sources */,
3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */,
@ -5619,7 +5582,6 @@
44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */,
A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */,
FB9A1DD83EF641A75ABBCE69 /* WaitlistScreenViewModelTests.swift in Sources */,
7F02063FB3D1C3E5601471A1 /* WelcomeScreenScreenViewModelTests.swift in Sources */,
3116693C5EB476E028990416 /* XCTestCase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -5715,9 +5677,16 @@
88F348E2CB14FF71CBBB665D /* AudioRoomTimelineItemContent.swift in Sources */,
E62EC30B39354A391E32A126 /* AudioRoomTimelineView.swift in Sources */,
9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */,
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */,
67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */,
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */,
64FF5CB4E35971255872E1BB /* AuthenticationServiceProxyProtocol.swift in Sources */,
9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */,
7A170A5A4A352954BB2A1B96 /* AuthenticationStartScreen.swift in Sources */,
E4F924DECC66389C1C810550 /* AuthenticationStartScreenBackgroundImage.swift in Sources */,
A4AF12D9D8BA34B3B7B55B08 /* AuthenticationStartScreenCoordinator.swift in Sources */,
0E3A2787C6AEC761A81A938A /* AuthenticationStartScreenModels.swift in Sources */,
E79B247A6DD28759636317EA /* AuthenticationStartScreenViewModel.swift in Sources */,
874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */,
6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */,
4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */,
D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */,
@ -5991,13 +5960,6 @@
CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */,
523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */,
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */,
7719778A682FDAC21445E9C8 /* OnboardingLogo.swift in Sources */,
7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */,
C0DC02E2B91DC76A4D1A0E7F /* OnboardingScreenBackgroundImage.swift in Sources */,
7CFCC177F0ED083867FAD9C9 /* OnboardingScreenCoordinator.swift in Sources */,
3A5BD701D1AC916AC534F52C /* OnboardingScreenModels.swift in Sources */,
A5C5C18671EDD2747AC16D2D /* OnboardingScreenViewModel.swift in Sources */,
4714991754A08B58B4D7ED85 /* OnboardingScreenViewModelProtocol.swift in Sources */,
3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */,
AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */,
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */,
@ -6349,11 +6311,6 @@
CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */,
63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */,
B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */,
D871C8CF46950F959C9A62C3 /* WelcomeScreen.swift in Sources */,
383055C6ABE5BE058CEE1DDB /* WelcomeScreenScreenCoordinator.swift in Sources */,
BD2BF1EC73FFB0C01552ECDA /* WelcomeScreenScreenModels.swift in Sources */,
DC1BB5EE5F4D9B6A1F98A77A /* WelcomeScreenScreenViewModel.swift in Sources */,
94CEF587A3994A36A46D8334 /* WelcomeScreenScreenViewModelProtocol.swift in Sources */,
08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */,
AE5AAD9E32511544FDFA5560 /* WindowManagerProtocol.swift in Sources */,
);
@ -6369,7 +6326,8 @@
44DA28B1E1F9C97C5795F7B3 /* AppLockSetupUITests.swift in Sources */,
BAC845780F17CCFBC5A9CA37 /* AppLockUITests.swift in Sources */,
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */,
ACF094CF3BF02DBFA6DFDE60 /* AuthenticationCoordinatorUITests.swift in Sources */,
2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */,
47597438020EC8144E535425 /* AuthenticationStartScreenUITests.swift in Sources */,
7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */,
94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */,
04778AA4D6AD2E153D7AAFF2 /* CallScreenUITests.swift in Sources */,
@ -6384,7 +6342,6 @@
6713835120D94BAA8ED7E3E5 /* MessageForwardingScreenUITests.swift in Sources */,
1830E5431DB426E2F3660D58 /* NotificationSettingsEditScreenUITests.swift in Sources */,
AF4232E6F08C3DB86FFA9BBD /* NotificationSettingsScreenUITests.swift in Sources */,
92133B170A1F917685E9FF78 /* OnboardingScreenUITests.swift in Sources */,
0CF81807BE5FBFC9E2BBCECF /* PollFormScreenUITests.swift in Sources */,
BA0D3DDCEDD97502DAC4B6E9 /* ReportContentScreenUITests.swift in Sources */,
F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */,
@ -6410,7 +6367,6 @@
84EFCB95F9DA2979C8042B26 /* UITestsSignalling.swift in Sources */,
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */,
2DA90E38FF4E696825810C1A /* WaitlistScreenUITests.swift in Sources */,
2185C1F6724C78FFF355D6FA /* WelcomeScreenScreenUITests.swift in Sources */,
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -7120,7 +7076,7 @@
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
requirement = {
kind = exactVersion;
version = 1.1.48;
version = 1.1.49;
};
};
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {

View File

@ -130,8 +130,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
"state" : {
"revision" : "08a2d19930095446fa75065ee555f590946265aa",
"version" : "1.1.48"
"revision" : "0361eac2610f0007f2a6880a88c750a1bbb405b9",
"version" : "1.1.49"
}
},
{

View File

@ -20,7 +20,7 @@ import MatrixRustSDK
import SwiftUI
import Version
class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, NotificationManagerDelegate, WindowManagerDelegate {
class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDelegate, NotificationManagerDelegate, WindowManagerDelegate {
private let stateMachine: AppCoordinatorStateMachine
private let navigationRootCoordinator: NavigationRootCoordinator
private let userSessionStore: UserSessionStoreProtocol
@ -43,7 +43,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
}
}
private var authenticationCoordinator: AuthenticationCoordinator?
private var authenticationFlowCoordinator: AuthenticationFlowCoordinator?
private let appLockFlowCoordinator: AppLockFlowCoordinator
// periphery:ignore - used to avoid deallocation
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
@ -189,7 +189,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
if stateMachine.state == .softLogout {
softLogoutCoordinator?.handleOIDCRedirectURL(url)
} else {
authenticationCoordinator?.handleOIDCRedirectURL(url)
authenticationFlowCoordinator?.handleOIDCRedirectURL(url)
}
case .genericCallLink(let url):
if let userSessionFlowCoordinator {
@ -209,11 +209,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
return false
}
// MARK: - AuthenticationCoordinatorDelegate
// MARK: - AuthenticationFlowCoordinatorDelegate
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
func authenticationFlowCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
self.userSession = userSession
authenticationCoordinator = nil
authenticationFlowCoordinator = nil
stateMachine.processEvent(.createdUserSession)
}
@ -393,22 +393,19 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
}
private func startAuthentication() {
let authenticationNavigationStackCoordinator = NavigationStackCoordinator()
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore,
encryptionKeyProvider: EncryptionKeyProvider(),
appSettings: appSettings)
authenticationCoordinator = AuthenticationCoordinator(authenticationService: authenticationService,
appLockService: appLockFlowCoordinator.appLockService,
bugReportService: ServiceLocator.shared.bugReportService,
navigationStackCoordinator: authenticationNavigationStackCoordinator,
appSettings: appSettings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController)
authenticationCoordinator?.delegate = self
authenticationFlowCoordinator = AuthenticationFlowCoordinator(authenticationService: authenticationService,
appLockService: appLockFlowCoordinator.appLockService,
bugReportService: ServiceLocator.shared.bugReportService,
navigationRootCoordinator: navigationRootCoordinator,
appSettings: appSettings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController)
authenticationFlowCoordinator?.delegate = self
authenticationCoordinator?.start()
navigationRootCoordinator.setRootCoordinator(authenticationNavigationStackCoordinator)
authenticationFlowCoordinator?.start()
}
private func startAuthenticationSoftLogout() {
@ -458,9 +455,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
fatalError("User session not setup")
}
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator())
let userSessionFlowCoordinator = UserSessionFlowCoordinator(userSession: userSession,
navigationSplitCoordinator: navigationSplitCoordinator,
navigationRootCoordinator: navigationRootCoordinator,
windowManager: windowManager,
appLockService: appLockFlowCoordinator.appLockService,
bugReportService: ServiceLocator.shared.bugReportService,
@ -487,8 +483,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
self.userSessionFlowCoordinator = userSessionFlowCoordinator
navigationRootCoordinator.setRootCoordinator(navigationSplitCoordinator)
if let storedAppRoute {
userSessionFlowCoordinator.handleAppRoute(storedAppRoute, animated: false)
}

View File

@ -22,7 +22,6 @@ final class AppSettings {
private enum UserDefaultsKeys: String {
case lastVersionLaunched
case seenInvites
case hasShownWelcomeScreen
case appLockNumberOfPINAttempts
case appLockNumberOfBiometricAttempts
case lastLoginDate
@ -109,9 +108,6 @@ final class AppSettings {
/// The task identifier used for background app refresh. Also used in main target's the Info.plist
let backgroundAppRefreshTaskIdentifier = "io.element.elementx.background.refresh"
@UserPreference(key: UserDefaultsKeys.hasShownWelcomeScreen, defaultValue: false, storageType: .userDefaults(store))
var hasShownWelcomeScreen: Bool
/// A URL where users can go read more about the app.
let websiteURL: URL = "https://element.io"
/// A URL that contains the app's logo that may be used when showing content in a web view.

View File

@ -18,14 +18,15 @@ import Combine
import SwiftUI
@MainActor
protocol AuthenticationCoordinatorDelegate: AnyObject {
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol)
protocol AuthenticationFlowCoordinatorDelegate: AnyObject {
func authenticationFlowCoordinator(didLoginWithSession userSession: UserSessionProtocol)
}
class AuthenticationCoordinator: CoordinatorProtocol {
class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
private let authenticationService: AuthenticationServiceProxyProtocol
private let appLockService: AppLockServiceProtocol
private let bugReportService: BugReportServiceProtocol
private let navigationRootCoordinator: NavigationRootCoordinator
private let navigationStackCoordinator: NavigationStackCoordinator
private let appSettings: AppSettings
private let analytics: AnalyticsService
@ -41,30 +42,36 @@ class AuthenticationCoordinator: CoordinatorProtocol {
// periphery:ignore - retaining purpose
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
weak var delegate: AuthenticationCoordinatorDelegate?
weak var delegate: AuthenticationFlowCoordinatorDelegate?
init(authenticationService: AuthenticationServiceProxyProtocol,
appLockService: AppLockServiceProtocol,
bugReportService: BugReportServiceProtocol,
navigationStackCoordinator: NavigationStackCoordinator,
navigationRootCoordinator: NavigationRootCoordinator,
appSettings: AppSettings,
analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol) {
self.authenticationService = authenticationService
self.appLockService = appLockService
self.bugReportService = bugReportService
self.navigationStackCoordinator = navigationStackCoordinator
self.navigationRootCoordinator = navigationRootCoordinator
self.appSettings = appSettings
self.analytics = analytics
self.userIndicatorController = userIndicatorController
navigationStackCoordinator = NavigationStackCoordinator()
}
func start() {
showOnboarding()
showStartScreen()
}
func stop() {
stopLoading()
func handleAppRoute(_ appRoute: AppRoute, animated: Bool) {
fatalError()
}
func clearRoute(animated: Bool) {
fatalError()
}
func handleOIDCRedirectURL(_ url: URL) {
@ -78,8 +85,8 @@ class AuthenticationCoordinator: CoordinatorProtocol {
// MARK: - Private
private func showOnboarding() {
let coordinator = OnboardingScreenCoordinator()
private func showStartScreen() {
let coordinator = AuthenticationStartScreenCoordinator()
coordinator.actions
.sink { [weak self] action in
@ -95,6 +102,8 @@ class AuthenticationCoordinator: CoordinatorProtocol {
.store(in: &cancellables)
navigationStackCoordinator.setRootCoordinator(coordinator)
navigationRootCoordinator.setRootCoordinator(navigationStackCoordinator)
}
private func showReportProblemScreen() {
@ -263,7 +272,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
} else if analytics.shouldShowAnalyticsPrompt {
showAnalyticsPrompt(userSession: userSession)
} else {
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
}
}
@ -279,7 +288,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
if analytics.shouldShowAnalyticsPrompt {
showAnalyticsPrompt(userSession: userSession)
} else {
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
}
case .forceLogout:
fatalError("The PIN creation flow should not fail.")
@ -299,7 +308,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
guard let self else { return }
switch action {
case .done:
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
}
}
.store(in: &cancellables)
@ -307,7 +316,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
navigationStackCoordinator.push(coordinator)
}
private static let loadingIndicatorIdentifier = "AuthenticationCoordinatorLoading"
private static let loadingIndicatorIdentifier = "authenticationFlowCoordinatorLoading"
private func startLoading() {
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,

View File

@ -131,7 +131,9 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
case .blockedUsers:
presentBlockedUsersScreen()
case .sessionVerification:
presentSessionVerificationScreen()
Task {
await self.presentSessionVerificationScreen()
}
case .accountSessions:
presentAccountSessionsListURL()
case .notifications:
@ -211,8 +213,8 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
navigationStackCoordinator.push(coordinator)
}
private func presentSessionVerificationScreen() {
guard let sessionVerificationController = parameters.userSession.sessionVerificationController else {
private func presentSessionVerificationScreen() async {
guard case let .success(sessionVerificationController) = await parameters.userSession.clientProxy.sessionVerificationControllerProxy() else {
fatalError("The sessionVerificationController should aways be valid at this point")
}

View File

@ -26,6 +26,7 @@ enum UserSessionFlowCoordinatorAction {
class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
private let userSession: UserSessionProtocol
private let navigationRootCoordinator: NavigationRootCoordinator
private let navigationSplitCoordinator: NavigationSplitCoordinator
private let windowManager: WindowManagerProtocol
private let bugReportService: BugReportServiceProtocol
@ -56,7 +57,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
}
init(userSession: UserSessionProtocol,
navigationSplitCoordinator: NavigationSplitCoordinator,
navigationRootCoordinator: NavigationRootCoordinator,
windowManager: WindowManagerProtocol,
appLockService: AppLockServiceProtocol,
bugReportService: BugReportServiceProtocol,
@ -65,11 +66,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
analytics: AnalyticsService) {
stateMachine = UserSessionFlowCoordinatorStateMachine()
self.userSession = userSession
self.navigationSplitCoordinator = navigationSplitCoordinator
self.navigationRootCoordinator = navigationRootCoordinator
self.windowManager = windowManager
self.bugReportService = bugReportService
self.appSettings = appSettings
navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator())
sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
@ -139,12 +142,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
}
func start() {
if !appSettings.hasShownWelcomeScreen {
stateMachine.processEvent(.startWithWelcomeScreen)
} else {
// Otherwise go straight to the home screen.
stateMachine.processEvent(.start)
}
stateMachine.processEvent(.start)
}
func stop() { }
@ -219,14 +217,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
case (.initial, .start, .roomList):
presentHomeScreen()
case (.initial, .startWithWelcomeScreen, .welcomeScreen):
presentHomeScreen()
presentWelcomeScreen()
case (.roomList, .presentWelcomeScreen, .welcomeScreen):
presentWelcomeScreen()
case (.welcomeScreen, .dismissedWelcomeScreen, .roomList):
break
case(.roomList, .selectRoom, .roomList):
break
case(.roomList, .deselectRoom, .roomList):
@ -238,7 +228,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
break
case (.roomList, .showSessionVerificationScreen, .sessionVerificationScreen):
presentSessionVerification(animated: animated)
Task {
await self.presentSessionVerification(animated: animated)
}
case (.sessionVerificationScreen, .dismissedSessionVerificationScreen, .roomList):
break
@ -341,21 +333,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
.store(in: &cancellables)
sidebarNavigationStackCoordinator.setRootCoordinator(coordinator)
}
private func presentWelcomeScreen() {
let welcomeScreenCoordinator = WelcomeScreenScreenCoordinator()
welcomeScreenCoordinator.actions.sink { [weak self] action in
switch action {
case .dismiss:
self?.navigationSplitCoordinator.setSheetCoordinator(nil)
}
}
.store(in: &cancellables)
navigationSplitCoordinator.setSheetCoordinator(welcomeScreenCoordinator) { [weak self] in
self?.stateMachine.processEvent(.dismissedWelcomeScreen)
}
navigationRootCoordinator.setRootCoordinator(navigationSplitCoordinator)
}
private func runLogoutFlow() async {
@ -405,8 +384,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
// MARK: Session verification
private func presentSessionVerification(animated: Bool) {
guard let sessionVerificationController = userSession.sessionVerificationController else {
private func presentSessionVerification(animated: Bool) async {
guard case let .success(sessionVerificationController) = await userSession.clientProxy.sessionVerificationControllerProxy() else {
fatalError("The sessionVerificationController should aways be valid at this point")
}

View File

@ -23,9 +23,6 @@ class UserSessionFlowCoordinatorStateMachine {
/// The initial state, used before the coordinator starts
case initial
/// Showing the welcome screen.
case welcomeScreen
/// Showing the home screen. The `selectedRoomID` represents the timeline shown on the detail panel (if any)
case roomList(selectedRoomID: String?)
@ -56,15 +53,6 @@ class UserSessionFlowCoordinatorStateMachine {
enum Event: EventType {
/// Start the user session flows.
case start
/// Starts the user session flows with the welcome screen.
/// **Note:** This is event is only for users who used the app before v1.1.8.
/// It can be removed once the older TestFlight builds have expired.
case startWithWelcomeScreen
/// Request presentation of the welcome screen.
case presentWelcomeScreen
/// The welcome screen has been dismissed.
case dismissedWelcomeScreen
/// Request presentation for a particular room
/// - Parameter roomID:the room identifier
@ -116,8 +104,6 @@ class UserSessionFlowCoordinatorStateMachine {
private func configure() {
stateMachine.addRoutes(event: .start, transitions: [.initial => .roomList(selectedRoomID: nil)])
stateMachine.addRoutes(event: .startWithWelcomeScreen, transitions: [.initial => .welcomeScreen])
stateMachine.addRoutes(event: .dismissedWelcomeScreen, transitions: [.welcomeScreen => .roomList(selectedRoomID: nil)])
stateMachine.addRouteMapping { event, fromState, _ in
switch (fromState, event) {
@ -158,9 +144,6 @@ class UserSessionFlowCoordinatorStateMachine {
case (.invitesScreen(let selectedRoomID), .dismissedInvitesScreen):
return .roomList(selectedRoomID: selectedRoomID)
case (.roomList, .presentWelcomeScreen):
return .welcomeScreen
case (.roomList(let selectedRoomID), .showLogoutConfirmationScreen):
return .logoutConfirmationScreen(selectedRoomID: selectedRoomID)
case (.logoutConfirmationScreen(let selectedRoomID), .dismissedLogoutConfirmationScreen):

View File

@ -38,6 +38,7 @@ extension ClientProxyMock {
actionsPublisher = PassthroughSubject<ClientProxyAction, Never>().eraseToAnyPublisher()
loadingStatePublisher = CurrentValuePublisher<ClientProxyLoadingState, Never>(.notLoading)
verificationStatePublisher = CurrentValuePublisher<SessionVerificationState, Never>(.unknown)
userAvatarURLPublisher = CurrentValueSubject<URL?, Never>(nil).asCurrentValuePublisher()

View File

@ -727,6 +727,11 @@ class ClientProxyMock: ClientProxyProtocol {
set(value) { underlyingLoadingStatePublisher = value }
}
var underlyingLoadingStatePublisher: CurrentValuePublisher<ClientProxyLoadingState, Never>!
var verificationStatePublisher: CurrentValuePublisher<SessionVerificationState, Never> {
get { return underlyingVerificationStatePublisher }
set(value) { underlyingVerificationStatePublisher = value }
}
var underlyingVerificationStatePublisher: CurrentValuePublisher<SessionVerificationState, Never>!
var userID: String {
get { return underlyingUserID }
set(value) { underlyingUserID = value }

View File

@ -27,7 +27,7 @@ enum A11yIdentifiers {
static let changeServerScreen = ChangeServer()
static let homeScreen = HomeScreen()
static let loginScreen = LoginScreen()
static let onboardingScreen = OnboardingScreen()
static let authenticationStartScreen = AuthenticationStartScreen()
static let reportContent = ReportContent()
static let roomScreen = RoomScreen()
static let roomDetailsScreen = RoomDetailsScreen()
@ -42,7 +42,6 @@ enum A11yIdentifiers {
static let createRoomScreen = CreateRoomScreen()
static let invitesScreen = InvitesScreen()
static let inviteUsersScreen = InviteUsersScreen()
static let welcomeScreen = WelcomeScreen()
static let migrationScreen = MigrationScreen()
static let notificationSettingsScreen = NotificationSettingsScreen()
static let notificationSettingsEditScreen = NotificationSettingsEditScreen()
@ -124,9 +123,9 @@ enum A11yIdentifiers {
let unsupportedServer = "login-unsupported_server"
}
struct OnboardingScreen {
let signIn = "onboarding-sign_in"
let hidden = "onboarding-hidden"
struct AuthenticationStartScreen {
let signIn = "authentication_start-sign_in"
let hidden = "authentication_start-hidden"
}
struct ReportContent {
@ -260,10 +259,6 @@ enum A11yIdentifiers {
}
}
struct WelcomeScreen {
let letsGo = "welcome_screen-lets_go"
}
struct MigrationScreen {
let message = "migration_screen-message"
}

View File

@ -21,7 +21,7 @@ struct AnalyticsPromptScreen: View {
@ObservedObject var context: AnalyticsPromptScreenViewModel.Context
var body: some View {
FullscreenDialog(topPadding: UIConstants.onboardingBreakerScreenTopPadding) {
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding) {
mainContent
} bottomContent: {
buttons

View File

@ -28,9 +28,7 @@ enum UIConstants {
static let actionButtonBottomPadding: CGFloat = 24
/// The padding used to the top of the view for breaker screens that don't have a navigation bar.
static let onboardingBreakerScreenTopPadding: CGFloat = 80
static let welcomeScreenTopPadding: CGFloat = 122
static let startScreenBreakerScreenTopPadding: CGFloat = 80
/// The height to use for top/bottom spacers to pad the views to fit the `maxContentHeight`.
static func spacerHeight(in geometry: GeometryProxy) -> CGFloat {

View File

@ -27,13 +27,13 @@ struct WaitingDialog<Content: View, BottomContent: View>: View {
private var contentTopPadding: CGFloat {
if verticalSizeClass == .compact {
// Reduced value for iPhones in landscape.
return UIConstants.onboardingBreakerScreenTopPadding
return UIConstants.startScreenBreakerScreenTopPadding
} else if horizontalSizeClass == .compact {
// The default value for portrait iPhones.
return 2 * UIConstants.onboardingBreakerScreenTopPadding
return 2 * UIConstants.startScreenBreakerScreenTopPadding
} else {
// Larger on iPad specifically for 11" in Landscape.
return 2.7 * UIConstants.onboardingBreakerScreenTopPadding
return 2.7 * UIConstants.startScreenBreakerScreenTopPadding
}
}
@ -43,7 +43,7 @@ struct WaitingDialog<Content: View, BottomContent: View>: View {
@ViewBuilder var bottomContent: () -> BottomContent
var body: some View {
FullscreenDialog(topPadding: UIConstants.onboardingBreakerScreenTopPadding, horizontalPadding: 0) {
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding, horizontalPadding: 0) {
content()
.padding(.top, contentTopPadding)
.padding(.horizontal, horizontalPadding)
@ -68,7 +68,7 @@ struct WaitingDialog<Content: View, BottomContent: View>: View {
GeometryReader { geometry in
VStack(spacing: -5) {
Color.white
.frame(maxHeight: UIConstants.onboardingBreakerScreenTopPadding)
.frame(maxHeight: UIConstants.startScreenBreakerScreenTopPadding)
Image(asset: Asset.Images.waitingGradient)
.resizable()

View File

@ -17,17 +17,17 @@
import Combine
import SwiftUI
final class OnboardingScreenCoordinator: CoordinatorProtocol {
private var viewModel: OnboardingScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<OnboardingScreenCoordinatorAction, Never> = .init()
final class AuthenticationStartScreenCoordinator: CoordinatorProtocol {
private var viewModel: AuthenticationStartScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<AuthenticationStartScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
var actions: AnyPublisher<OnboardingScreenCoordinatorAction, Never> {
var actions: AnyPublisher<AuthenticationStartScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
viewModel = OnboardingScreenViewModel()
viewModel = AuthenticationStartScreenViewModel()
}
// MARK: - Public
@ -48,6 +48,6 @@ final class OnboardingScreenCoordinator: CoordinatorProtocol {
}
func toPresentable() -> AnyView {
AnyView(OnboardingScreen(context: viewModel.context))
AnyView(AuthenticationStartScreen(context: viewModel.context))
}
}

View File

@ -18,19 +18,19 @@ import SwiftUI
// MARK: - Coordinator
enum OnboardingScreenCoordinatorAction {
enum AuthenticationStartScreenCoordinatorAction {
case login
case reportProblem
}
enum OnboardingScreenViewModelAction {
enum AuthenticationStartScreenViewModelAction {
case login
case reportProblem
}
struct OnboardingScreenViewState: BindableState { }
struct AuthenticationStartScreenViewState: BindableState { }
enum OnboardingScreenViewAction {
enum AuthenticationStartScreenViewAction {
case login
case reportProblem
}

View File

@ -17,20 +17,20 @@
import Combine
import SwiftUI
typealias OnboardingScreenViewModelType = StateStoreViewModel<OnboardingScreenViewState, OnboardingScreenViewAction>
typealias AuthenticationStartScreenViewModelType = StateStoreViewModel<AuthenticationStartScreenViewState, AuthenticationStartScreenViewAction>
class OnboardingScreenViewModel: OnboardingScreenViewModelType, OnboardingScreenViewModelProtocol {
private var actionsSubject: PassthroughSubject<OnboardingScreenViewModelAction, Never> = .init()
class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType, AuthenticationStartScreenViewModelProtocol {
private var actionsSubject: PassthroughSubject<AuthenticationStartScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<OnboardingScreenViewModelAction, Never> {
var actions: AnyPublisher<AuthenticationStartScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
super.init(initialViewState: OnboardingScreenViewState())
super.init(initialViewState: AuthenticationStartScreenViewState())
}
override func process(viewAction: OnboardingScreenViewAction) {
override func process(viewAction: AuthenticationStartScreenViewAction) {
switch viewAction {
case .login:
actionsSubject.send(.login)

View File

@ -17,7 +17,7 @@
import Combine
@MainActor
protocol OnboardingScreenViewModelProtocol {
var actions: AnyPublisher<OnboardingScreenViewModelAction, Never> { get }
var context: OnboardingScreenViewModelType.Context { get }
protocol AuthenticationStartScreenViewModelProtocol {
var actions: AnyPublisher<AuthenticationStartScreenViewModelAction, Never> { get }
var context: AuthenticationStartScreenViewModelType.Context { get }
}

View File

@ -17,7 +17,7 @@
import SwiftUI
/// The app's logo styled to fit on various launch pages.
struct OnboardingLogo: View {
struct AuthenticationStartLogo: View {
@Environment(\.colorScheme) private var colorScheme
/// Set to `true` when using on top of `Asset.Images.launchBackground`

View File

@ -17,10 +17,10 @@
import SwiftUI
/// The screen shown at the beginning of the onboarding flow.
struct OnboardingScreen: View {
struct AuthenticationStartScreen: View {
@Environment(\.verticalSizeClass) private var verticalSizeClass
@ObservedObject var context: OnboardingScreenViewModel.Context
@ObservedObject var context: AuthenticationStartScreenViewModel.Context
var body: some View {
GeometryReader { geometry in
@ -30,7 +30,7 @@ struct OnboardingScreen: View {
content
.frame(width: geometry.size.width)
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.hidden)
.accessibilityIdentifier(A11yIdentifiers.authenticationStartScreen.hidden)
buttons
.frame(width: geometry.size.width)
@ -49,13 +49,14 @@ struct OnboardingScreen: View {
Text(L10n.commonReportAProblem)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
.padding(.bottom)
}
.frame(width: geometry.size.width)
}
}
.navigationBarHidden(true)
.background {
OnboardingScreenBackgroundImage()
AuthenticationStartScreenBackgroundImage()
}
}
@ -66,7 +67,7 @@ struct OnboardingScreen: View {
if verticalSizeClass == .regular {
Spacer()
OnboardingLogo(isOnGradient: true)
AuthenticationStartLogo(isOnGradient: true)
}
Spacer()
@ -98,7 +99,7 @@ struct OnboardingScreen: View {
Text(L10n.actionContinue)
}
.buttonStyle(.compound(.primary))
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.signIn)
.accessibilityIdentifier(A11yIdentifiers.authenticationStartScreen.signIn)
}
.padding(.horizontal, verticalSizeClass == .compact ? 128 : 24)
.readableFrame()
@ -107,10 +108,10 @@ struct OnboardingScreen: View {
// MARK: - Previews
struct OnboardingScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = OnboardingScreenViewModel()
struct AuthenticationStartScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = AuthenticationStartScreenViewModel()
static var previews: some View {
OnboardingScreen(context: viewModel.context)
AuthenticationStartScreen(context: viewModel.context)
}
}

View File

@ -17,7 +17,7 @@
import SwiftUI
/// The background gradient shown on the launch, splash and onboarding screens.
struct OnboardingScreenBackgroundImage: View {
struct AuthenticationStartScreenBackgroundImage: View {
var body: some View {
Image(asset: Asset.Images.launchBackground)
.resizable()

View File

@ -75,11 +75,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
if state.securityBannerMode != .dismissed {
state.securityBannerMode = .sessionVerification
}
case (.unverifiedLastSession, .incomplete):
state.requiresExtraAccountSetup = true
if state.securityBannerMode != .dismissed {
state.securityBannerMode = .sessionVerification
}
case (.verified, .disabled):
state.requiresExtraAccountSetup = true
state.securityBannerMode = .none

View File

@ -33,11 +33,11 @@ struct PlaceholderScreen: View {
let showsBackgroundGradient: Bool
var body: some View {
OnboardingLogo(isOnGradient: showsBackgroundGradient)
AuthenticationStartLogo(isOnGradient: showsBackgroundGradient)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background {
if showsBackgroundGradient {
OnboardingScreenBackgroundImage()
AuthenticationStartScreenBackgroundImage()
}
}
.background()

View File

@ -100,9 +100,9 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
showSavingIndicator()
switch await roomProxy.resetPowerLevels() {
case .success(let success):
case .success:
showSuccessIndicator()
case .failure(let failure):
case .failure:
state.bindings.alertInfo = AlertInfo(id: .error)
}

View File

@ -53,9 +53,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
case (.unverified, _):
state.showSecuritySectionBadge = true
state.securitySectionMode = .sessionVerification
case (.unverifiedLastSession, .incomplete):
state.showSecuritySectionBadge = true
state.securitySectionMode = .sessionVerification
case (.verified, .disabled):
state.showSecuritySectionBadge = true
state.securitySectionMode = .secureBackup

View File

@ -1,92 +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 SwiftUI
struct WelcomeScreen: View {
@ObservedObject var context: WelcomeScreenScreenViewModel.Context
var body: some View {
FullscreenDialog(topPadding: UIConstants.welcomeScreenTopPadding) {
mainContent
} bottomContent: {
button
}
.background(OnboardingScreenBackgroundImage())
.environment(\.backgroundStyle, AnyShapeStyle(Color.clear))
.onAppear {
context.send(viewAction: .appeared)
}
}
private var mainContent: some View {
VStack(spacing: 80) {
header
list
}
}
private var header: some View {
VStack(spacing: 32) {
OnboardingLogo(isOnGradient: true)
.scaleEffect(x: 0.75, y: 0.75)
.padding(.vertical, -20)
Text(L10n.screenWelcomeTitle(InfoPlistReader.main.bundleDisplayName))
.font(Font.compound.headingLGBold)
.foregroundColor(Color.compound.textPrimary)
.multilineTextAlignment(.center)
}
}
private var list: some View {
VStack(alignment: .leading, spacing: 4) {
RoundedLabelItem(title: L10n.screenWelcomeBullet2, listPosition: .top) {
Image(systemName: "lock")
.foregroundColor(.compound.iconSecondaryAlpha)
}
RoundedLabelItem(title: L10n.screenWelcomeBullet3, listPosition: .bottom) {
Image(systemName: "exclamationmark.bubble")
.padding(.horizontal, -3)
.foregroundColor(.compound.iconSecondaryAlpha)
}
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity)
.environment(\.backgroundStyle, AnyShapeStyle(.compound.bgCanvasDefaultLevel1))
}
@ViewBuilder
private var button: some View {
Button {
context.send(viewAction: .doneTapped)
} label: {
Text(L10n.screenWelcomeButton)
}
.buttonStyle(.compound(.primary))
.accessibilityIdentifier(A11yIdentifiers.welcomeScreen.letsGo)
}
}
// MARK: - Previews
struct WelcomeScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = WelcomeScreenScreenViewModel()
static var previews: some View {
WelcomeScreen(context: viewModel.context)
}
}

View File

@ -1,51 +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
enum WelcomeScreenScreenCoordinatorAction {
case dismiss
}
final class WelcomeScreenScreenCoordinator: CoordinatorProtocol {
private var viewModel: WelcomeScreenScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<WelcomeScreenScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
var actions: AnyPublisher<WelcomeScreenScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
viewModel = WelcomeScreenScreenViewModel()
}
func start() {
viewModel.actions.sink { [weak self] action in
guard let self else { return }
switch action {
case .dismiss:
actionsSubject.send(.dismiss)
}
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(WelcomeScreen(context: viewModel.context))
}
}

View File

@ -1,28 +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 Foundation
enum WelcomeScreenScreenViewModelAction {
case dismiss
}
struct WelcomeScreenScreenViewState: BindableState { }
enum WelcomeScreenScreenViewAction {
case doneTapped
case appeared
}

View File

@ -1,45 +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 WelcomeScreenScreenViewModelType = StateStoreViewModel<WelcomeScreenScreenViewState, WelcomeScreenScreenViewAction>
class WelcomeScreenScreenViewModel: WelcomeScreenScreenViewModelType, WelcomeScreenScreenViewModelProtocol {
let appSettings: AppSettings
private var actionsSubject: PassthroughSubject<WelcomeScreenScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<WelcomeScreenScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(appSettings: AppSettings = ServiceLocator.shared.settings) {
self.appSettings = appSettings
super.init(initialViewState: WelcomeScreenScreenViewState())
}
// MARK: - Public
override func process(viewAction: WelcomeScreenScreenViewAction) {
switch viewAction {
case .doneTapped:
actionsSubject.send(.dismiss)
case .appeared:
appSettings.hasShownWelcomeScreen = true
}
}
}

View File

@ -1,23 +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
@MainActor
protocol WelcomeScreenScreenViewModelProtocol {
var actions: AnyPublisher<WelcomeScreenScreenViewModelAction, Never> { get }
var context: WelcomeScreenScreenViewModelType.Context { get }
}

View File

@ -41,6 +41,9 @@ class ClientProxy: ClientProxyProtocol {
// periphery:ignore - required for instance retention in the rust codebase
private var ignoredUsersListenerTaskHandle: TaskHandle?
// periphery:ignore - required for instance retention in the rust codebase
private var verificationStateListenerTaskHandle: TaskHandle?
private var delegateHandle: TaskHandle?
// These following summary providers both operate on the same allRooms() list but
@ -111,6 +114,11 @@ class ClientProxy: ClientProxyProtocol {
loadingStateSubject.asCurrentValuePublisher()
}
private let verificationStateSubject = CurrentValueSubject<SessionVerificationState, Never>(.unknown)
var verificationStatePublisher: CurrentValuePublisher<SessionVerificationState, Never> {
verificationStateSubject.asCurrentValuePublisher()
}
init(client: ClientProtocol,
backgroundTaskService: BackgroundTaskServiceProtocol,
appSettings: AppSettings,
@ -151,6 +159,25 @@ class ClientProxy: ClientProxyProtocol {
ignoredUsersListenerTaskHandle = client.subscribeToIgnoredUsers(listener: IgnoredUsersListenerProxy { [weak self] ignoredUsers in
self?.ignoredUsersSubject.send(ignoredUsers)
})
updateVerificationState(client.encryption().verificationState())
verificationStateListenerTaskHandle = client.encryption().verificationStateListener(listener: VerificationStateListenerProxy { [weak self] verificationState in
self?.updateVerificationState(verificationState)
})
}
private func updateVerificationState(_ verificationState: VerificationState) {
let verificationState: SessionVerificationState = switch verificationState {
case .unknown:
.unknown
case .unverified:
.unverified
case .verified:
.verified
}
verificationStateSubject.send(verificationState)
}
var userID: String {
@ -745,6 +772,18 @@ private class RoomListServiceSyncIndicatorListenerProxy: RoomListServiceSyncIndi
}
}
private class VerificationStateListenerProxy: VerificationStateListener {
private let onUpdateClosure: (VerificationState) -> Void
init(onUpdateClosure: @escaping (VerificationState) -> Void) {
self.onUpdateClosure = onUpdateClosure
}
func onUpdate(status: VerificationState) {
onUpdateClosure(status)
}
}
private class ClientDelegateWrapper: ClientDelegate {
private let authErrorCallback: (Bool) -> Void

View File

@ -71,12 +71,20 @@ struct PusherConfiguration {
let lang: String
}
enum SessionVerificationState {
case unknown
case verified
case unverified
}
// sourcery: AutoMockable
protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
var actionsPublisher: AnyPublisher<ClientProxyAction, Never> { get }
var loadingStatePublisher: CurrentValuePublisher<ClientProxyLoadingState, Never> { get }
var verificationStatePublisher: CurrentValuePublisher<SessionVerificationState, Never> { get }
var userID: String { get }
var deviceID: String? { get }

View File

@ -22,8 +22,6 @@ class UserSession: UserSessionProtocol {
private var cancellables = Set<AnyCancellable>()
private var retrieveSessionVerificationControllerTask: Task<Void, Never>?
private var authErrorCancellable: AnyCancellable?
var userID: String { clientProxy.userID }
@ -36,20 +34,6 @@ class UserSession: UserSessionProtocol {
let callbacks = PassthroughSubject<UserSessionCallback, Never>()
private(set) var sessionVerificationController: SessionVerificationControllerProxyProtocol? {
didSet {
sessionVerificationController?.callbacks.sink { [weak self] callback in
switch callback {
case .finished:
self?.sessionVerificationStateSubject.send(.verified)
default:
break
}
}
.store(in: &cancellables)
}
}
let sessionSecurityStateSubject = CurrentValueSubject<SessionSecurityState, Never>(.init(verificationState: .unknown, recoveryState: .unknown))
var sessionSecurityStatePublisher: CurrentValuePublisher<SessionSecurityState, Never> {
sessionSecurityStateSubject.asCurrentValuePublisher()
@ -60,15 +44,6 @@ class UserSession: UserSessionProtocol {
self.mediaProvider = mediaProvider
self.voiceMessageMediaManager = voiceMessageMediaManager
clientProxy.actionsPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] callback in
if callback.isSyncUpdate {
self?.checkSessionVerificationState()
}
}
.store(in: &cancellables)
authErrorCancellable = clientProxy.actionsPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] callback in
@ -82,7 +57,7 @@ class UserSession: UserSessionProtocol {
}
}
Publishers.CombineLatest(sessionVerificationStateSubject, clientProxy.secureBackupController.recoveryState)
Publishers.CombineLatest(clientProxy.verificationStatePublisher, clientProxy.secureBackupController.recoveryState)
.map {
MXLog.info("Session security state changed, verificationState: \($0), recoveryState: \($1)")
return SessionSecurityState(verificationState: $0, recoveryState: $1)
@ -94,62 +69,4 @@ class UserSession: UserSessionProtocol {
}
.store(in: &cancellables)
}
// MARK: - Private
private func checkSessionVerificationState() {
guard retrieveSessionVerificationControllerTask == nil else {
MXLog.info("Session verification state check already in progress")
return
}
guard sessionVerificationController == nil else {
Task {
await updateSessionVerificationState()
}
return
}
MXLog.info("Retrieving session verification controller")
retrieveSessionVerificationControllerTask = Task {
switch await clientProxy.sessionVerificationControllerProxy() {
case .success(let sessionVerificationController):
self.sessionVerificationController = sessionVerificationController
await updateSessionVerificationState()
retrieveSessionVerificationControllerTask = nil
case .failure(let error):
MXLog.info("Failed getting session verification controller with error: \(error). Will retry on the next sync update.")
}
}
}
private func updateSessionVerificationState() async {
guard let sessionVerificationController else {
fatalError("This point should never be reached")
}
MXLog.info("Checking session verification state")
guard case let .success(isVerified) = await sessionVerificationController.isVerified() else {
MXLog.error("Failed checking verification state. Will retry on the next sync update.")
return
}
if isVerified {
sessionVerificationStateSubject.send(.verified)
} else {
guard case let .success(isLastDevice) = await clientProxy.isOnlyDeviceLeft() else {
MXLog.error("Failed checking isLastDevice. Will retry on the next sync update.")
return
}
if isLastDevice {
sessionVerificationStateSubject.send(.unverifiedLastSession)
} else {
sessionVerificationStateSubject.send(.unverified)
}
}
}
}

View File

@ -21,13 +21,6 @@ enum UserSessionCallback {
case didReceiveAuthError(isSoftLogout: Bool)
}
enum SessionVerificationState {
case unknown
case verified
case unverified
case unverifiedLastSession
}
struct SessionSecurityState: Equatable {
let verificationState: SessionVerificationState
let recoveryState: SecureBackupRecoveryState
@ -43,7 +36,6 @@ protocol UserSessionProtocol {
var voiceMessageMediaManager: VoiceMessageMediaManagerProtocol { get }
var sessionSecurityStatePublisher: CurrentValuePublisher<SessionSecurityState, Never> { get }
var sessionVerificationController: SessionVerificationControllerProxyProtocol? { get }
var callbacks: PassthroughSubject<UserSessionCallback, Never> { get }
}

View File

@ -53,8 +53,12 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, WindowManagerDelegate {
func start() {
guard let screenID = ProcessInfo.testScreenID else { fatalError("Unable to launch with unknown screen.") }
let mockScreen = MockScreen(id: screenID, windowManager: windowManager)
navigationRootCoordinator.setRootCoordinator(mockScreen.coordinator)
let mockScreen = MockScreen(id: screenID, windowManager: windowManager, navigationRootCoordinator: navigationRootCoordinator)
if let coordinator = mockScreen.coordinator {
navigationRootCoordinator.setRootCoordinator(coordinator)
}
self.mockScreen = mockScreen
}
@ -71,8 +75,16 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, WindowManagerDelegate {
// Set up the alternate window for the App Lock flow coordinator tests.
guard let screenID = ProcessInfo.testScreenID, screenID == .appLockFlow || screenID == .appLockFlowDisabled else { return }
let screen = MockScreen(id: screenID == .appLockFlow ? .appLockFlowAlternateWindow : .appLockFlowDisabledAlternateWindow, windowManager: windowManager)
windowManager.alternateWindow.rootViewController = UIHostingController(rootView: screen.coordinator.toPresentable().statusBarHidden())
let screen = MockScreen(id: screenID == .appLockFlow ? .appLockFlowAlternateWindow : .appLockFlowDisabledAlternateWindow,
windowManager: windowManager,
navigationRootCoordinator: navigationRootCoordinator)
guard let coordinator = screen.coordinator else {
fatalError()
}
windowManager.alternateWindow.rootViewController = UIHostingController(rootView: coordinator.toPresentable().statusBarHidden())
alternateWindowMockScreen = screen
}
}
@ -81,16 +93,20 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, WindowManagerDelegate {
class MockScreen: Identifiable {
let id: UITestsScreenIdentifier
let windowManager: WindowManagerProtocol
let navigationRootCoordinator: NavigationRootCoordinator
private var retainedState = [Any]()
private var cancellables = Set<AnyCancellable>()
init(id: UITestsScreenIdentifier, windowManager: WindowManagerProtocol) {
init(id: UITestsScreenIdentifier,
windowManager: WindowManagerProtocol,
navigationRootCoordinator: NavigationRootCoordinator) {
self.id = id
self.windowManager = windowManager
self.navigationRootCoordinator = navigationRootCoordinator
}
lazy var coordinator: CoordinatorProtocol = {
lazy var coordinator: CoordinatorProtocol? = {
switch id {
case .login:
let navigationStackCoordinator = NavigationStackCoordinator()
@ -132,17 +148,16 @@ class MockScreen: Identifiable {
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .authenticationFlow:
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
appLockService: AppLockServiceMock(),
bugReportService: BugReportServiceMock(),
navigationStackCoordinator: navigationStackCoordinator,
appSettings: ServiceLocator.shared.settings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController)
retainedState.append(coordinator)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
let flowCoordinator = AuthenticationFlowCoordinator(authenticationService: MockAuthenticationServiceProxy(),
appLockService: AppLockServiceMock(),
bugReportService: BugReportServiceMock(),
navigationRootCoordinator: navigationRootCoordinator,
appSettings: ServiceLocator.shared.settings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController)
flowCoordinator.start()
retainedState.append(flowCoordinator)
return nil
case .softLogout:
let credentials = SoftLogoutScreenCredentials(userID: "@mock:matrix.org",
homeserverName: "matrix.org",
@ -331,8 +346,8 @@ class MockScreen: Identifiable {
notificationSettings: notificationSettings,
isModallyPresented: false)
return NotificationSettingsScreenCoordinator(parameters: parameters)
case .onboarding:
return OnboardingScreenCoordinator()
case .authenticationStartScreen:
return AuthenticationStartScreenCoordinator()
case .roomPlainNoAvatar:
let navigationStackCoordinator = NavigationStackCoordinator()
let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(with: .init(name: "Some room name", avatarURL: nil)),
@ -562,10 +577,9 @@ class MockScreen: Identifiable {
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
ServiceLocator.shared.settings.migratedAccounts[clientProxy.userID] = true
ServiceLocator.shared.settings.hasShownWelcomeScreen = true
let flowCoordinator = UserSessionFlowCoordinator(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider(), voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
navigationSplitCoordinator: navigationSplitCoordinator,
navigationRootCoordinator: navigationRootCoordinator,
windowManager: windowManager,
appLockService: AppLockService(keychainController: KeychainControllerMock(),
appSettings: ServiceLocator.shared.settings),
@ -578,7 +592,7 @@ class MockScreen: Identifiable {
retainedState.append(flowCoordinator)
return navigationSplitCoordinator
return nil
case .roomDetailsScreen:
let navigationStackCoordinator = NavigationStackCoordinator()
let members: [RoomMemberProxyMock] = [.mockAlice, .mockBob, .mockCharlie]

View File

@ -41,7 +41,7 @@ enum UITestsScreenIdentifier: String {
case bugReportWithScreenshot
case notificationSettingsScreen
case notificationSettingsScreenMismatchConfiguration
case onboarding
case authenticationStartScreen
case roomPlainNoAvatar
case roomEncryptedWithAvatar
case roomSmallTimeline

View File

@ -101,13 +101,6 @@ extension XCUIApplication {
currentTestCase.waitForExpectations(timeout: 300.0)
}
// Welcome screen may be shown as an overlay.
if buttons[A11yIdentifiers.welcomeScreen.letsGo].waitForExistence(timeout: 1.0) {
let goButton = buttons[A11yIdentifiers.welcomeScreen.letsGo]
XCTAssertTrue(goButton.waitForExistence(timeout: 1.0))
goButton.tap()
}
// Wait for the home screen to become visible.
let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar]
// Timeouts are huge because we're waiting for the server.

Binary file not shown.

View File

@ -17,7 +17,7 @@
import XCTest
@MainActor
class AuthenticationCoordinatorUITests: XCTestCase {
class AuthenticationFlowCoordinatorUITests: XCTestCase {
func testLoginWithPassword() async throws {
// Given the authentication flow.
let app = Application.launch(.authenticationFlow)

View File

@ -17,7 +17,7 @@
import XCTest
@MainActor
class OnboardingScreenUITests: XCTestCase {
class AuthenticationStartScreenUITests: XCTestCase {
func testInitialStateComponents() async throws {
let app = Application.launch(.onboarding)
try await app.assertScreenshot(.onboarding)

View File

@ -1,20 +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 XCTest
@MainActor
class WelcomeScreenScreenUITests: XCTestCase { }

View File

@ -18,6 +18,6 @@ import XCTest
@testable import ElementX
class OnboardingScreenViewModelTests: XCTestCase {
class AuthenticationStartScreenViewModelTests: XCTestCase {
// Nothing to test, the view model has no mutable state.
}

View File

@ -17,62 +17,4 @@ import Combine
@testable import ElementX
import XCTest
final class UserSessionTests: XCTestCase {
var userSession: UserSession!
var clientProxy: ClientProxyMock!
let actionsPublisher = PassthroughSubject<ClientProxyAction, Never>()
private var cancellables = Set<AnyCancellable>()
override func setUpWithError() throws {
clientProxy = ClientProxyMock(.init(userID: "@test:user.net"))
clientProxy.actionsPublisher = actionsPublisher.eraseToAnyPublisher()
cancellables.removeAll()
userSession = UserSession(clientProxy: clientProxy,
mediaProvider: MockMediaProvider(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
}
func test_whenUserSessionReceivesSyncUpdateAndSessionControllerRetrievedAndSessionNotVerified_sessionVerificationNeededEventReceived() throws {
let expectation = expectation(description: "SessionVerificationNeeded expectation")
userSession.sessionSecurityStatePublisher.sink { securityState in
if securityState.verificationState == .unverified {
expectation.fulfill()
}
}
.store(in: &cancellables)
let controller = SessionVerificationControllerProxyMock.configureMock(callbacks: PassthroughSubject<SessionVerificationControllerProxyCallback, Never>(),
isVerified: false,
requestDelay: .zero)
clientProxy.sessionVerificationControllerProxyReturnValue = .success(controller)
actionsPublisher.send(.receivedSyncUpdate)
waitForExpectations(timeout: 1.0)
}
func test_whenUserSessionReceivesSyncUpdateAndSessionIsVerified_didVerifySessionEventReceived() throws {
let expectation = expectation(description: "DidVerifySessionEvent expectation")
let controller = SessionVerificationControllerProxyMock.configureMock(callbacks: PassthroughSubject<SessionVerificationControllerProxyCallback, Never>(),
isVerified: false,
requestDelay: .zero)
clientProxy.sessionVerificationControllerProxyReturnValue = .success(controller)
controller.callbacks.sink { value in
switch value {
case .finished:
expectation.fulfill()
default:
break
}
}
.store(in: &cancellables)
actionsPublisher.send(.receivedSyncUpdate)
controller.callbacks.send(.finished)
waitForExpectations(timeout: 1.0)
}
}
final class UserSessionTests: XCTestCase { }

View File

@ -1,22 +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 XCTest
@testable import ElementX
@MainActor
class WelcomeScreenScreenViewModelTests: XCTestCase { }

View File

@ -48,7 +48,7 @@ packages:
# Element/Matrix dependencies
MatrixRustSDK:
url: https://github.com/matrix-org/matrix-rust-components-swift
exactVersion: 1.1.48
exactVersion: 1.1.49
# path: ../matrix-rust-sdk
Compound:
url: https://github.com/element-hq/compound-ios