mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Onboarding flow coordinator and FTUE changes (#2578)
Fixes #2595, fixes #2594, fixes #2593, fixes #2592, fixes #2591
This commit is contained in:
parent
9e6b6ba60a
commit
a62c96f1c5
@ -22,6 +22,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C070FD43DC6BF4E50217965A /* LocalizationTests.swift */; };
|
||||
01681E8B20AD6F0D237F2DC1 /* IdentityConfirmedScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */; };
|
||||
0180C44B997EDA8D21F883AC /* RoomNotificationSettingsCustomSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */; };
|
||||
01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */; };
|
||||
020C530986D7B97631877FEF /* TimelineItemMacContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4AD793D50748F8997E5B15 /* TimelineItemMacContextMenu.swift */; };
|
||||
@ -36,6 +37,7 @@
|
||||
04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422724361B6555364C43281E /* RoomHeaderView.swift */; };
|
||||
04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */; };
|
||||
059173B3C77056C406906B6D /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = D4DA544B2520BFA65D6DB4BB /* target.yml */; };
|
||||
05BAB510CBC2ED35C154ADD0 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */; };
|
||||
05EC896A4B9AF4A56670C0BB /* SessionVerificationUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */; };
|
||||
066A1E9B94723EE9F3038044 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
|
||||
06AA515C7053FD7E17A5CF81 /* RoomNotificationSettingsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */; };
|
||||
@ -56,13 +58,13 @@
|
||||
09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */; };
|
||||
09EF4222EEBBA1A7B8F4071E /* VoiceMessageRecordingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E61DDB42C0DE429C0955D8 /* VoiceMessageRecordingButton.swift */; };
|
||||
0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */; };
|
||||
0AA0477E063E72B786A983CF /* AnalyticsPromptScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E1FF2DA52B1DE7CAEC5422 /* AnalyticsPromptScreenViewModel.swift */; };
|
||||
0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */; };
|
||||
0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; };
|
||||
0B57C2399B9E1CE5CE0D8005 /* ComposerToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D121B4FCFC38DBCC17BCC6D6 /* ComposerToolbar.swift */; };
|
||||
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 */; };
|
||||
0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.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 */; };
|
||||
@ -82,6 +84,7 @@
|
||||
0F9E38A75337D0146652ACAB /* BackgroundTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DFCAA239095A116976E32C4 /* BackgroundTaskTests.swift */; };
|
||||
1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0376C429FAB1687C3D905F3E /* MockCoder.swift */; };
|
||||
119AE9A3FC6E0606C1146528 /* NotificationSettingsEditScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */; };
|
||||
11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */; };
|
||||
126EE01D8BEAEF26105D83C5 /* RoomDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */; };
|
||||
12C867E85E6D12EEDFD0B127 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */; };
|
||||
12CCA59536EDD99A3272CF77 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; };
|
||||
@ -149,6 +152,7 @@
|
||||
241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */; };
|
||||
244407B18B2F2D6466BA5961 /* RoomChangeRolesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */; };
|
||||
245F7FE5961BD10C145A26E0 /* UITimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA689E792E679F5E3956F21 /* UITimelineView.swift */; };
|
||||
24A1BBADAC43DC3F3A7347DA /* AnalyticsPromptScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */; };
|
||||
24A75F72EEB7561B82D726FD /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; };
|
||||
24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; };
|
||||
24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; };
|
||||
@ -182,6 +186,7 @@
|
||||
2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
|
||||
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; };
|
||||
2BBA132149DEBED6624084A8 /* MessageForwardingScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FAE373A7F20780BA84B59C /* MessageForwardingScreenCoordinator.swift */; };
|
||||
2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; };
|
||||
2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; };
|
||||
2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; };
|
||||
2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; };
|
||||
@ -250,6 +255,7 @@
|
||||
3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; };
|
||||
3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */; };
|
||||
3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */; };
|
||||
3E7B65C2C97748D5D65AAA8B /* NotificationPermissionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */; };
|
||||
3EC5A41F9FB7DD63A4DC6144 /* RoomChangeRolesScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */; };
|
||||
3EC698F80DDEEFA273857841 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 893777A4997BBDB68079D4F5 /* ArrayTests.swift */; };
|
||||
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
|
||||
@ -278,6 +284,7 @@
|
||||
44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */; };
|
||||
44DA28B1E1F9C97C5795F7B3 /* AppLockSetupUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */; };
|
||||
44F0E1B576C7599DF8022071 /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 391D11F92DFC91666AA1503F /* SwiftOGG */; };
|
||||
454311EAC17D778E19F46592 /* NotificationPermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */; };
|
||||
454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F219838588C62198E726E3 /* LABiometryType.swift */; };
|
||||
4557192F5B15A8D9BB920232 /* AdvancedSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E492690C8B27A892C194CC4 /* AdvancedSettingsScreenCoordinator.swift */; };
|
||||
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; };
|
||||
@ -292,13 +299,14 @@
|
||||
47FF70C051A991FB65CDBCF3 /* RoomScreenInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0135A608FFAD86E6674EE730 /* RoomScreenInteractionHandler.swift */; };
|
||||
4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */; };
|
||||
484202C5D50983442D24D061 /* AttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */; };
|
||||
489BB6A733D3DA0FE7062650 /* IdentityConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */; };
|
||||
491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3203C6566DC17B7AECC1B7FD /* RoomNotificationSettingsUserDefinedScreen.swift */; };
|
||||
492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
|
||||
4940B439681767BE9D78CFDB /* AppLockSetupBiometricsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */; };
|
||||
496CC9D59ACFAB84FD9B3B5F /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */; };
|
||||
49814A48470F347426513B07 /* TimelineReadReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */; };
|
||||
49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */; };
|
||||
4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; };
|
||||
4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */; };
|
||||
4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; };
|
||||
4A9CEEE612D6D8B3DDBD28BA /* RoomListFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */; };
|
||||
4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */; };
|
||||
@ -326,6 +334,7 @@
|
||||
50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; };
|
||||
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; };
|
||||
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
|
||||
5139F4BD5A5DF6F8D11A9BDE /* NotificationPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */; };
|
||||
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
|
||||
51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; };
|
||||
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
|
||||
@ -349,9 +358,8 @@
|
||||
565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; };
|
||||
56BAB81A0D03C2EF09B86294 /* ComposerToolbarModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA188BB0A216D763E46E3279 /* ComposerToolbarModels.swift */; };
|
||||
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; };
|
||||
5770C4906668C6D3008A2AC9 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */; };
|
||||
5710AAB27D5D866292C1FE06 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */; };
|
||||
5780E444F405AA1304E1C23E /* DeveloperOptionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */; };
|
||||
584590D0EA548152A393E72C /* HomeScreenSessionVerificationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = E71C28CF29CD05B6D6AE8580 /* HomeScreenSessionVerificationBanner.swift */; };
|
||||
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
|
||||
5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */; };
|
||||
5897A59DDBD3592282092223 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */; };
|
||||
@ -375,8 +383,8 @@
|
||||
5E0F2E612718BB4397A6D40A /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */; };
|
||||
5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEB970F500BFB248443FA1 /* BloomView.swift */; };
|
||||
5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; };
|
||||
5F28C9146694B381BB82E18C /* AnalyticsPromptScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B65A314DF40B6BBF775C2BC /* AnalyticsPromptScreenCoordinator.swift */; };
|
||||
5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; };
|
||||
601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; };
|
||||
60ED66E63A169E47489348A8 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 886A0A498FA01E8EDD451D05 /* Sentry */; };
|
||||
6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */; };
|
||||
617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; };
|
||||
@ -435,6 +443,7 @@
|
||||
6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; };
|
||||
6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; };
|
||||
6D6E651ACACE27E9C5690818 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE47A97726F0675DEE387BF9 /* TypingIndicatorView.swift */; };
|
||||
6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */; };
|
||||
6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */; };
|
||||
6E4E401BE97AC241DA7C7716 /* AppLockSetupSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */; };
|
||||
6E63704717F17593A475D152 /* RoomNotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */; };
|
||||
@ -449,6 +458,7 @@
|
||||
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */; };
|
||||
706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; };
|
||||
706F79A39BDB32F592B8C2C7 /* UIKitBackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */; };
|
||||
707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */; };
|
||||
70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */; };
|
||||
719E7AAD1F8E68F68F30FECD /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; };
|
||||
71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */; };
|
||||
@ -466,6 +476,7 @@
|
||||
755395927DDD6EBDDA5E217A /* SettingsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */; };
|
||||
755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */; };
|
||||
762DAF94846C7AC8550F1CC1 /* MediaPlayerProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */; };
|
||||
762DB0973865293F0C3D3D7B /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */; };
|
||||
763D69741D58D2B650BC1FC9 /* CallScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */; };
|
||||
7640A4B412CACF15D143CCD4 /* Strings+SAS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B172057567E049007A5C4D92 /* Strings+SAS.swift */; };
|
||||
764AFCC225B044CF5F9B41E5 /* PaginationIndicatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */; };
|
||||
@ -474,6 +485,7 @@
|
||||
76BA28216FBAF83B2D86A027 /* InvitesScreenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2A71915C1F075E403F559C /* InvitesScreenCell.swift */; };
|
||||
7708976CEE6AFB5CFAEFBA68 /* PillTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */; };
|
||||
7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; };
|
||||
77574A519A4E484880053EAD /* IdentityConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */; };
|
||||
77693820498ABF3508814D49 /* AppLockServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */; };
|
||||
77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; };
|
||||
77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */; };
|
||||
@ -485,7 +497,6 @@
|
||||
795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
|
||||
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 */; };
|
||||
@ -598,6 +609,7 @@
|
||||
934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */; };
|
||||
93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */; };
|
||||
93A549135E6C027A0D823BFE /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 593FBBF394712F2963E98A0B /* DTCoreText */; };
|
||||
93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */; };
|
||||
93BA4A81B6D893271101F9F0 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; };
|
||||
93BAF04D9CCBC0A8841414D0 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */; };
|
||||
9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */; };
|
||||
@ -619,7 +631,6 @@
|
||||
988BA75A182738150894A23F /* UserIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */; };
|
||||
9912F9EB2D6589141A2957B4 /* AppLockScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */; };
|
||||
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
||||
9965CB800CE6BC74ACA969FC /* EncryptedHistoryRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */; };
|
||||
99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; };
|
||||
9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
|
||||
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */; };
|
||||
@ -632,6 +643,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 */; };
|
||||
9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.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 */; };
|
||||
@ -641,7 +653,6 @@
|
||||
9DD5AA10E85137140FEA86A3 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; };
|
||||
9DD84E014ADFB2DD813022D5 /* RoomDetailsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */; };
|
||||
9DE801D278AC34737467F937 /* VoiceMessageMediaManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */; };
|
||||
9DF3F6318A4402305F5EB869 /* AnalyticsPromptScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8002D0392A476D2758B291 /* AnalyticsPromptScreen.swift */; };
|
||||
9E838A62918E47BC72D6640D /* UserIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */; };
|
||||
9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; };
|
||||
9F11E743EA01482E78A438B0 /* GlobalSearchScreenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */; };
|
||||
@ -704,6 +715,7 @@
|
||||
AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */; };
|
||||
AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */; };
|
||||
AA93B3F9B5DD097DEF79F981 /* NotificationSettingsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBB0328F2887BF0A65BC5D49 /* NotificationSettingsEditScreen.swift */; };
|
||||
AADE7C2497A7B55D8BED7BD6 /* IdentityConfirmedScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */; };
|
||||
AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; };
|
||||
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; };
|
||||
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; };
|
||||
@ -722,7 +734,6 @@
|
||||
AFA1F2543DFF7B45DF68ACD6 /* CompletionSuggestionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 170BF6F7923A5C3792442F27 /* CompletionSuggestionModels.swift */; };
|
||||
B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */; };
|
||||
B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; };
|
||||
B09DC6E3D0EE87C4D4ABFAB3 /* EncryptedHistoryRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */; };
|
||||
B0CB16349B96262AA65A04AF /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = A05AF81DDD14AD58CB0E1B9B /* Version */; };
|
||||
B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */; };
|
||||
B13774779EA19FDD7A35A4A8 /* RoomRolesAndPermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */; };
|
||||
@ -731,7 +742,6 @@
|
||||
B188D0907A4D38AAAF6FEFA8 /* AppLockSetupFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */; };
|
||||
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; };
|
||||
B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; };
|
||||
B27D3190784F85916DA1C394 /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B1EE0908B2BF9212436AD3E /* SessionVerificationScreenStateMachine.swift */; };
|
||||
B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; };
|
||||
B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */; };
|
||||
B3EDDEC1839BB5A3747624BB /* FormButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A1CCDEE545CB6453B084BF /* FormButtonStyles.swift */; };
|
||||
@ -779,6 +789,7 @@
|
||||
BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; };
|
||||
BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; };
|
||||
BD0BE20DBCE31253AE4490A1 /* RoomListFiltersEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC1DDB2293A51EA4C2739351 /* RoomListFiltersEmptyStateView.swift */; };
|
||||
BD11E639CF566A9DA8FCA717 /* RoundedLabelItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */; };
|
||||
BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */; };
|
||||
BD6685592716CA957D7BAAC4 /* RoomChangeRolesScreenSelectedItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */; };
|
||||
BD6D98676111DA8FC2BE4908 /* InvitesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86873A768B13069BB5CAECF6 /* InvitesScreenViewModelProtocol.swift */; };
|
||||
@ -804,6 +815,7 @@
|
||||
C32765D740C81AD4C42E8F50 /* CreateRoomFlowParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */; };
|
||||
C3317EF833AB4060988DF098 /* SAS.strings in Resources */ = {isa = PBXBuildFile; fileRef = 135FC689EA39AE1D34153B58 /* SAS.strings */; };
|
||||
C3522917C0C367C403429EEC /* CoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */; };
|
||||
C3BB6887CF13B19182E81F87 /* IdentityConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */; };
|
||||
C4078364FD9FA00EA9D00A15 /* RoomMembersListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */; };
|
||||
C413D36D44F89DE63D3ADFA4 /* ReportContentScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */; };
|
||||
C4180F418235DAD9DD173951 /* TemplateScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */; };
|
||||
@ -823,6 +835,7 @@
|
||||
C7ABEBECDC513F7887DACF66 /* ProgressMaskModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68010886142843705E342645 /* ProgressMaskModifier.swift */; };
|
||||
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
|
||||
C85C7A201E4CFDA477ACEBEB /* AppLockSetupSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */; };
|
||||
C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */; };
|
||||
C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */; };
|
||||
C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; };
|
||||
C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E0B4A34E69BD2132BEC521 /* MessageText.swift */; };
|
||||
@ -855,6 +868,7 @@
|
||||
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */; };
|
||||
CFEC53440C572CEEABC4A6A0 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
|
||||
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
||||
D02DEB36D32A72A1B365E452 /* SessionVerificationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */; };
|
||||
D050D7756E92CA061ED0ABF0 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */; };
|
||||
D0550B8E0AE2C0CDBE52C88F /* MediaPlayerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */; };
|
||||
D0A965852D6C04138FA55181 /* SecureBackupLogoutConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */; };
|
||||
@ -865,6 +879,7 @@
|
||||
D1E29F345F1220E1AF1BE9DF /* ReadReceiptsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB0A77874B29D79DDFC051AC /* ReadReceiptsSummaryView.swift */; };
|
||||
D1EEF0CB0F5D9C15E224E670 /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */; };
|
||||
D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; };
|
||||
D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; };
|
||||
D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; };
|
||||
D29E046C1E3045E0346C479D /* RoomRolesAndPermissionsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */; };
|
||||
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
|
||||
@ -874,8 +889,8 @@
|
||||
D415764645491F10344FC6AC /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F18AECC9D38C2B6D85F99C /* Publisher.swift */; };
|
||||
D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */; };
|
||||
D46C33F8B61B55F0C8C2D15F /* LocationRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */; };
|
||||
D4ACF3276F5D0DA28D4028C9 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8196D64EB9CF2AF1F43E4ED1 /* AnalyticsPromptScreenViewModelProtocol.swift */; };
|
||||
D4D5595C4A2A702CFF4E94FF /* HeroImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */; };
|
||||
D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */; };
|
||||
D53B80EF02C1062E68659EDD /* ReportContentViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */; };
|
||||
D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */; };
|
||||
D5681C80D8281560AACE0035 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045253F9967A535EE5B16691 /* Label.swift */; };
|
||||
@ -887,17 +902,18 @@
|
||||
D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; };
|
||||
DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */; };
|
||||
DB079D1929B5A5F52D207C83 /* RoomDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */; };
|
||||
DB65401349C143DFF883E2B0 /* AnalyticsPromptScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */; };
|
||||
DBC8D1DBFE9F9CA7662BC8AA /* RoomPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */; };
|
||||
DC08ADC41E792086A340A8B3 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
|
||||
DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */; };
|
||||
DC77E9DB2CFBE84A2BDF20C5 /* RoomRolesAndPermissionsFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */; };
|
||||
DCFE7CB3B9A104330BBB96AD /* AnalyticsPromptScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */; };
|
||||
DDB47D29C6865669288BF87C /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; };
|
||||
DDFBDEE1DC32BDD5488F898C /* ClientProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */; };
|
||||
DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; };
|
||||
@ -932,7 +948,6 @@
|
||||
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 */; };
|
||||
E62EC30B39354A391E32A126 /* AudioRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */; };
|
||||
@ -950,7 +965,6 @@
|
||||
E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */; };
|
||||
E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */; };
|
||||
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 */; };
|
||||
EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; };
|
||||
EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; };
|
||||
@ -997,7 +1011,6 @@
|
||||
F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; };
|
||||
F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; };
|
||||
F421FD5979EF53C8204BDC77 /* SecureBackupLogoutConfirmationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC09F30B0E1010951952BDC /* SecureBackupLogoutConfirmationScreenUITests.swift */; };
|
||||
F4433EF57B4BB3C077F8B00E /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD9E0FFA29EAACFF3AB9732 /* SessionVerificationScreenViewModel.swift */; };
|
||||
F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; };
|
||||
F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; };
|
||||
F508683B76EF7B23BB2CBD6D /* TimelineItemPlainStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */; };
|
||||
@ -1104,6 +1117,7 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = "<group>"; };
|
||||
00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = "<group>"; };
|
||||
00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
0135A608FFAD86E6674EE730 /* RoomScreenInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenInteractionHandler.swift; sourceTree = "<group>"; };
|
||||
01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenModels.swift; sourceTree = "<group>"; };
|
||||
@ -1193,10 +1207,12 @@
|
||||
15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModel.swift; sourceTree = "<group>"; };
|
||||
15F30E7AE8A303E8FEC2499E /* ReadReceiptCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceiptCell.swift; sourceTree = "<group>"; };
|
||||
16037EE9E9A52AF37B7818E3 /* AnalyticsSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = "<group>"; };
|
||||
16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = "<group>"; };
|
||||
170BF6F7923A5C3792442F27 /* CompletionSuggestionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionModels.swift; sourceTree = "<group>"; };
|
||||
1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = "<group>"; };
|
||||
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = "<group>"; };
|
||||
18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; };
|
||||
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||
1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReadReceiptsView.swift; sourceTree = "<group>"; };
|
||||
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
|
||||
@ -1210,7 +1226,6 @@
|
||||
1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURITests.swift; sourceTree = "<group>"; };
|
||||
1AB58EF0176D4CFB1040DA22 /* WaitlistScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyMock.swift; sourceTree = "<group>"; };
|
||||
1B1EE0908B2BF9212436AD3E /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = "<group>"; };
|
||||
1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillAttachmentViewProvider.swift; sourceTree = "<group>"; };
|
||||
1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenModels.swift; sourceTree = "<group>"; };
|
||||
@ -1227,6 +1242,7 @@
|
||||
1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
||||
1D8866FE1CCCF10305FCACBC /* CallScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenUITests.swift; sourceTree = "<group>"; };
|
||||
1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenModels.swift; sourceTree = "<group>"; };
|
||||
1DB34B0C74CD242FED9DD069 /* LoginScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenUITests.swift; sourceTree = "<group>"; };
|
||||
1DE7969EBCAF078813E18EA1 /* RoomRolesAndPermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenModels.swift; sourceTree = "<group>"; };
|
||||
1DF8F7A3AD83D04C08D75E01 /* RoomDetailsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1238,6 +1254,7 @@
|
||||
1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiLoaderProtocol.swift; sourceTree = "<group>"; };
|
||||
20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMapProtocol.swift; sourceTree = "<group>"; };
|
||||
20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
2141693488CE5446BB391964 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
|
||||
216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1282,7 +1299,6 @@
|
||||
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>"; };
|
||||
2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; };
|
||||
@ -1301,6 +1317,7 @@
|
||||
2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = "<group>"; };
|
||||
2FD0E68C42CA7DDCD4CAD68D /* MentionSuggestionItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionSuggestionItemView.swift; sourceTree = "<group>"; };
|
||||
303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreen.swift; sourceTree = "<group>"; };
|
||||
309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = "<group>"; };
|
||||
30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = "<group>"; };
|
||||
314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = "<group>"; };
|
||||
@ -1352,6 +1369,7 @@
|
||||
3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAppearance.swift; sourceTree = "<group>"; };
|
||||
3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenSelectedItem.swift; sourceTree = "<group>"; };
|
||||
3D9FCE4D1E3A81AC1CC5CB91 /* AppLockSetupSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenModels.swift; sourceTree = "<group>"; };
|
||||
3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingTests.swift; sourceTree = "<group>"; };
|
||||
3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTaskService.swift; sourceTree = "<group>"; };
|
||||
3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
@ -1388,6 +1406,7 @@
|
||||
45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = "<group>"; };
|
||||
466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenModels.swift; sourceTree = "<group>"; };
|
||||
46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsAppCoordinator.swift; sourceTree = "<group>"; };
|
||||
46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreen.swift; sourceTree = "<group>"; };
|
||||
46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
46F52419AEEDA2C006CB7181 /* NotificationSettingsEditScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenUITests.swift; sourceTree = "<group>"; };
|
||||
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1412,7 +1431,6 @@
|
||||
4AB7D7DAAAF662DED9D02379 /* MockMediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaLoader.swift; sourceTree = "<group>"; };
|
||||
4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = "<group>"; };
|
||||
4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; };
|
||||
4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = "<group>"; };
|
||||
@ -1462,6 +1480,7 @@
|
||||
58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenUITests.swift; sourceTree = "<group>"; };
|
||||
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; };
|
||||
595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenCoordinator.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>"; };
|
||||
@ -1479,7 +1498,7 @@
|
||||
5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
5F12E996BFBEB43815189ABF /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uk; path = uk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionProtocol.swift; sourceTree = "<group>"; };
|
||||
5F8002D0392A476D2758B291 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = "<group>"; };
|
||||
5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = "<group>"; };
|
||||
6033779EB37259F27F938937 /* ClientProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
60F18AECC9D38C2B6D85F99C /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = "<group>"; };
|
||||
612EF972F2A1800682D32C5E /* StickerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
@ -1491,7 +1510,6 @@
|
||||
62B07B296D7A9D2F09120853 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = "<group>"; };
|
||||
638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = "<group>"; };
|
||||
6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
63E1FF2DA52B1DE7CAEC5422 /* AnalyticsPromptScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenModels.swift; sourceTree = "<group>"; };
|
||||
648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridableAvatarImage.swift; sourceTree = "<group>"; };
|
||||
@ -1522,6 +1540,7 @@
|
||||
6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreen.swift; sourceTree = "<group>"; };
|
||||
6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenHeaderView.swift; sourceTree = "<group>"; };
|
||||
6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProvider.swift; sourceTree = "<group>"; };
|
||||
6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsScreenIdentifier.swift; sourceTree = "<group>"; };
|
||||
6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationUITests.swift; sourceTree = "<group>"; };
|
||||
@ -1550,7 +1569,6 @@
|
||||
7310D8DFE01AF45F0689C3AA /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = "<group>"; };
|
||||
7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||
7447C0AD7EF302CD027D6230 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
745323FCF9AF21A117252C53 /* RoundedLabelItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedLabelItem.swift; sourceTree = "<group>"; };
|
||||
74611A4182DCF5F4D42696EC /* XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestCase.swift; sourceTree = "<group>"; };
|
||||
7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@ -1561,7 +1579,6 @@
|
||||
74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
7509AB72755DCC4B4E721B36 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signposter.swift; sourceTree = "<group>"; };
|
||||
75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedHistoryRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
76310030C831D4610A705603 /* URLComponentsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsTests.swift; sourceTree = "<group>"; };
|
||||
772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
7773CBFDBD458E0B7E270507 /* PillView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillView.swift; sourceTree = "<group>"; };
|
||||
@ -1569,11 +1586,14 @@
|
||||
78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinatorTests.swift; sourceTree = "<group>"; };
|
||||
7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerMock.swift; sourceTree = "<group>"; };
|
||||
796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
7A5D2323D7B6BF4913EB7EED /* landscape_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = landscape_test_image.jpg; sourceTree = "<group>"; };
|
||||
7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportViewModelTests.swift; sourceTree = "<group>"; };
|
||||
7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
7B04BD3874D736127A8156B8 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
7B19B2BCC779ED934E0BBC2A /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
|
||||
7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpiringTaskRunner.swift; sourceTree = "<group>"; };
|
||||
@ -1582,6 +1602,7 @@
|
||||
7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowCoordinatorProtocol.swift; sourceTree = "<group>"; };
|
||||
7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
7CA3F8E905DF50BF22ECC18F /* ThreadDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadDecorator.swift; sourceTree = "<group>"; };
|
||||
7D0CBC76C80E04345E11F2DB /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
||||
7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactoryProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1593,22 +1614,21 @@
|
||||
7EC2F1622C5BBABED6012E12 /* HeroImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroImage.swift; sourceTree = "<group>"; };
|
||||
7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceProtocol.swift; sourceTree = "<group>"; };
|
||||
7FB2253D36E81E045E1CB432 /* Duration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Duration.swift; sourceTree = "<group>"; };
|
||||
7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = "<group>"; };
|
||||
80C4927D09099497233E9980 /* WaitlistScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreen.swift; sourceTree = "<group>"; };
|
||||
80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageEventStringBuilder.swift; sourceTree = "<group>"; };
|
||||
818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
8196D64EB9CF2AF1F43E4ED1 /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
81B17B1F29448D1B9049B11C /* ReportContentScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
81B17DB1BC3B0C62AF84D230 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCornerShape.swift; sourceTree = "<group>"; };
|
||||
840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; };
|
||||
84311D707B09854D67F78BBF /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersViewModelTests.swift; sourceTree = "<group>"; };
|
||||
84816E0D2F34E368BF64FA60 /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = "<group>"; };
|
||||
848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreen.swift; sourceTree = "<group>"; };
|
||||
84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
@ -1661,6 +1681,7 @@
|
||||
90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = "<group>"; };
|
||||
913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = "<group>"; };
|
||||
91831D7042EADD0CC2B5EC36 /* SecureBackupScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenUITests.swift; sourceTree = "<group>"; };
|
||||
91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCAuthenticationPresenter.swift; sourceTree = "<group>"; };
|
||||
92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTask.swift; sourceTree = "<group>"; };
|
||||
@ -1691,12 +1712,13 @@
|
||||
9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = landscape_test_video.mov; sourceTree = "<group>"; };
|
||||
9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceProtocol.swift; sourceTree = "<group>"; };
|
||||
9B06663F7858E45882E63471 /* StaticLocationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreen.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenCoordinator.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>"; };
|
||||
9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = "<group>"; };
|
||||
9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
@ -1733,6 +1755,7 @@
|
||||
A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = "<group>"; };
|
||||
A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = "<group>"; };
|
||||
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
||||
A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@ -1763,7 +1786,6 @@
|
||||
AD9CB3B9DFA353AB2B7CD9F8 /* NotificationSettingsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
ADB35E2DB4EFE8E6F3959629 /* InviteUsersScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenUITests.swift; sourceTree = "<group>"; };
|
||||
ADCB8A232D3A8FB3E16A7303 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
ADD9E0FFA29EAACFF3AB9732 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientMock.swift; sourceTree = "<group>"; };
|
||||
AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessorTests.swift; sourceTree = "<group>"; };
|
||||
AE40D4A5DD857AC16EED945A /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = "<group>"; };
|
||||
@ -1773,12 +1795,12 @@
|
||||
AF042B0FB2EE88977C91E330 /* portrait_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = portrait_test_image.jpg; sourceTree = "<group>"; };
|
||||
AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptUITests.swift; sourceTree = "<group>"; };
|
||||
AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = "<group>"; };
|
||||
AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; };
|
||||
AFEF489B8E2450E2BA1A314E /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomEventStringBuilder.swift; sourceTree = "<group>"; };
|
||||
B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
B172057567E049007A5C4D92 /* Strings+SAS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+SAS.swift"; sourceTree = "<group>"; };
|
||||
B1E227F34BE43B08E098796E /* TestablePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestablePreview.swift; sourceTree = "<group>"; };
|
||||
B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinatorProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1833,6 +1855,7 @@
|
||||
BCF54536699ACEE3DB6BA3CB /* CompletionSuggestionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionService.swift; sourceTree = "<group>"; };
|
||||
BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationContent.swift; sourceTree = "<group>"; };
|
||||
BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemReplyDetails.swift; sourceTree = "<group>"; };
|
||||
BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStoreProtocol.swift; sourceTree = "<group>"; };
|
||||
BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@ -1855,6 +1878,7 @@
|
||||
C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenModels.swift; sourceTree = "<group>"; };
|
||||
C2E9B841EE4878283ECDB554 /* InviteUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreen.swift; sourceTree = "<group>"; };
|
||||
C2F079B5DBD0D85FEA687AAE /* SDKGeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKGeneratedMocks.swift; sourceTree = "<group>"; };
|
||||
C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingFlowCoordinator.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>"; };
|
||||
C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1911,7 +1935,6 @@
|
||||
CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
|
||||
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = "<group>"; };
|
||||
D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedHistoryRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = "<group>"; };
|
||||
D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
|
||||
@ -1964,6 +1987,7 @@
|
||||
DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.swift; sourceTree = "<group>"; };
|
||||
DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = "<group>"; };
|
||||
DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = "<group>"; };
|
||||
DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedLabelItem.swift; sourceTree = "<group>"; };
|
||||
DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenUITests.swift; sourceTree = "<group>"; };
|
||||
DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaFileHandleProxy.swift; sourceTree = "<group>"; };
|
||||
DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationViewModelTests.swift; sourceTree = "<group>"; };
|
||||
@ -1992,6 +2016,7 @@
|
||||
E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteURLParserTests.swift; sourceTree = "<group>"; };
|
||||
E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = "<group>"; };
|
||||
E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = "<group>"; };
|
||||
E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; };
|
||||
E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
@ -2000,7 +2025,6 @@
|
||||
E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = "<group>"; };
|
||||
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
|
||||
E71C28CF29CD05B6D6AE8580 /* HomeScreenSessionVerificationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenSessionVerificationBanner.swift; sourceTree = "<group>"; };
|
||||
E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProviderProtocol.swift; sourceTree = "<group>"; };
|
||||
E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@ -2017,6 +2041,7 @@
|
||||
EA880E78AF4BD24E45A7808C /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
|
||||
EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenModels.swift; sourceTree = "<group>"; };
|
||||
EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsNotificationCenter.swift; sourceTree = "<group>"; };
|
||||
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = "<group>"; };
|
||||
ECB08484CD5D77C9BF97AA78 /* WaitlistScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenUITests.swift; sourceTree = "<group>"; };
|
||||
@ -2025,6 +2050,7 @@
|
||||
ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfiguration.swift; sourceTree = "<group>"; };
|
||||
ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = "<group>"; };
|
||||
ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||
ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
|
||||
ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = "<group>"; };
|
||||
ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
@ -2255,15 +2281,6 @@
|
||||
path = Logging;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
076087FC60064C702EF94796 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5F8002D0392A476D2758B291 /* AnalyticsPromptScreen.swift */,
|
||||
745323FCF9AF21A117252C53 /* RoundedLabelItem.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0787F81684E503024BD0C051 /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2621,19 +2638,6 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3153FCA3F4B0E88B16D99D12 /* SessionVerificationScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A96A67AD0E32C48941EFBB3 /* SessionVerificationScreenCoordinator.swift */,
|
||||
4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */,
|
||||
1B1EE0908B2BF9212436AD3E /* SessionVerificationScreenStateMachine.swift */,
|
||||
ADD9E0FFA29EAACFF3AB9732 /* SessionVerificationScreenViewModel.swift */,
|
||||
B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */,
|
||||
914D71CD209A34A8C142CB93 /* View */,
|
||||
);
|
||||
path = SessionVerificationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
31CE4DA53232AA534057F912 /* Mocks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2679,6 +2683,7 @@
|
||||
648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */,
|
||||
C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */,
|
||||
839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */,
|
||||
DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */,
|
||||
E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */,
|
||||
);
|
||||
path = Views;
|
||||
@ -2704,6 +2709,18 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
336A13CA8A1DD526D9C41DD4 /* IdentityConfirmationScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */,
|
||||
7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */,
|
||||
EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */,
|
||||
7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */,
|
||||
DDC32FD8B94AA19C4FC062AD /* View */,
|
||||
);
|
||||
path = IdentityConfirmationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
337015ADFBA3AB96660DB3A6 /* Generated */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2862,6 +2879,14 @@
|
||||
path = SupportingFiles;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4044C040B64B9F077298C947 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
405B00F139AEE3994601B36A = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3092,7 +3117,6 @@
|
||||
05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */,
|
||||
ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */,
|
||||
C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */,
|
||||
E71C28CF29CD05B6D6AE8580 /* HomeScreenSessionVerificationBanner.swift */,
|
||||
037A5661B26EC6BE068188D7 /* Filters */,
|
||||
);
|
||||
path = View;
|
||||
@ -3166,6 +3190,7 @@
|
||||
0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */,
|
||||
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */,
|
||||
7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */,
|
||||
C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */,
|
||||
9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */,
|
||||
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */,
|
||||
D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */,
|
||||
@ -3263,18 +3288,6 @@
|
||||
path = SecureBackupLogoutConfirmationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
669239C03835CD8B51E0FFDB /* AnalyticsPromptScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B65A314DF40B6BBF775C2BC /* AnalyticsPromptScreenCoordinator.swift */,
|
||||
840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */,
|
||||
63E1FF2DA52B1DE7CAEC5422 /* AnalyticsPromptScreenViewModel.swift */,
|
||||
8196D64EB9CF2AF1F43E4ED1 /* AnalyticsPromptScreenViewModelProtocol.swift */,
|
||||
076087FC60064C702EF94796 /* View */,
|
||||
);
|
||||
path = AnalyticsPromptScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6709362D60732DED2069AE0F /* MediaPlayer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3333,6 +3346,14 @@
|
||||
path = TimelineItemContent;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D7503E64A458DD09E65A3F7 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6DE13A7AE6587B079F4049D7 /* Notification */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3701,6 +3722,11 @@
|
||||
7DA2A18CFD03E0BACE6B5C4B /* AnalyticsPromptScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */,
|
||||
18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */,
|
||||
6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */,
|
||||
7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */,
|
||||
4044C040B64B9F077298C947 /* View */,
|
||||
);
|
||||
path = AnalyticsPromptScreen;
|
||||
sourceTree = "<group>";
|
||||
@ -3866,6 +3892,10 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7DA2A18CFD03E0BACE6B5C4B /* AnalyticsPromptScreen */,
|
||||
336A13CA8A1DD526D9C41DD4 /* IdentityConfirmationScreen */,
|
||||
F6D661C666128C74BF0A7482 /* IdentityConfirmedScreen */,
|
||||
F526F4FE387B32380592BA53 /* NotificationPermissionsScreen */,
|
||||
C1CD278862878F9545608040 /* SessionVerificationScreen */,
|
||||
);
|
||||
path = Onboarding;
|
||||
sourceTree = "<group>";
|
||||
@ -3909,14 +3939,6 @@
|
||||
path = LoginScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
914D71CD209A34A8C142CB93 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84816E0D2F34E368BF64FA60 /* SessionVerificationScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92E99C57D7F92ED16F73282C /* ElementCall */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4054,6 +4076,14 @@
|
||||
path = Templates;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9C0C1CB9E16302C00AB4956D /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
46D0BA44B1838E65B507B277 /* NotificationPermissionsScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9C4193C4524B35FD6B94B5A9 /* Pills */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4195,6 +4225,14 @@
|
||||
path = LayoutTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A722D372674EE5687E1A67E4 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A78C2592419CA4C76FBA8FD2 /* Application */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4360,7 +4398,6 @@
|
||||
CA8F098AE48D958B4257EB24 /* CallInviteRoomTimelineView.swift */,
|
||||
6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */,
|
||||
471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */,
|
||||
75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */,
|
||||
56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */,
|
||||
E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */,
|
||||
F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */,
|
||||
@ -4515,6 +4552,19 @@
|
||||
path = CreateRoom;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C1CD278862878F9545608040 /* SessionVerificationScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */,
|
||||
AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */,
|
||||
161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */,
|
||||
ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */,
|
||||
A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */,
|
||||
A722D372674EE5687E1A67E4 /* View */,
|
||||
);
|
||||
path = SessionVerificationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA15BB3F6C62B35AE2C281A9 /* Provider */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4634,7 +4684,6 @@
|
||||
D977D4E565C06D3F41C8F8FC /* Virtual */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */,
|
||||
0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */,
|
||||
DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */,
|
||||
C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */,
|
||||
@ -4663,6 +4712,14 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDC32FD8B94AA19C4FC062AD /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDF77194AB6E167891D0A8F3 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4716,7 +4773,6 @@
|
||||
E59565F441830B19DBAE567C /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
669239C03835CD8B51E0FFDB /* AnalyticsPromptScreen */,
|
||||
13263FFEA7749D822B51AA90 /* AppLock */,
|
||||
E74CD7681375AD2EAA34D66B /* Authentication */,
|
||||
295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */,
|
||||
@ -4751,7 +4807,6 @@
|
||||
7B890CCD20B037760BFDF957 /* RoomRolesAndPermissionsScreen */,
|
||||
679E9837ECA8D6776079D16E /* RoomScreen */,
|
||||
2565414373E6F68005966B8E /* SecureBackup */,
|
||||
3153FCA3F4B0E88B16D99D12 /* SessionVerificationScreen */,
|
||||
70B74A432C241E56A7ACE610 /* Settings */,
|
||||
EC4545C7E37E8294D3FE6800 /* StartChatScreen */,
|
||||
);
|
||||
@ -4912,6 +4967,18 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F526F4FE387B32380592BA53 /* NotificationPermissionsScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */,
|
||||
1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */,
|
||||
BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */,
|
||||
20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */,
|
||||
9C0C1CB9E16302C00AB4956D /* View */,
|
||||
);
|
||||
path = NotificationPermissionsScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F5A65D1D3B83593598DC278D /* EmojiPickerScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4924,6 +4991,18 @@
|
||||
path = EmojiPickerScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6D661C666128C74BF0A7482 /* IdentityConfirmedScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */,
|
||||
3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */,
|
||||
9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */,
|
||||
8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */,
|
||||
6D7503E64A458DD09E65A3F7 /* View */,
|
||||
);
|
||||
path = IdentityConfirmedScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F84100ED0C09031BAB7BB77E /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -5638,11 +5717,11 @@
|
||||
F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */,
|
||||
54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */,
|
||||
8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */,
|
||||
9DF3F6318A4402305F5EB869 /* AnalyticsPromptScreen.swift in Sources */,
|
||||
5F28C9146694B381BB82E18C /* AnalyticsPromptScreenCoordinator.swift in Sources */,
|
||||
496CC9D59ACFAB84FD9B3B5F /* AnalyticsPromptScreenModels.swift in Sources */,
|
||||
0AA0477E063E72B786A983CF /* AnalyticsPromptScreenViewModel.swift in Sources */,
|
||||
D4ACF3276F5D0DA28D4028C9 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */,
|
||||
24A1BBADAC43DC3F3A7347DA /* AnalyticsPromptScreen.swift in Sources */,
|
||||
DCFE7CB3B9A104330BBB96AD /* AnalyticsPromptScreenCoordinator.swift in Sources */,
|
||||
6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */,
|
||||
DB65401349C143DFF883E2B0 /* AnalyticsPromptScreenViewModel.swift in Sources */,
|
||||
05BAB510CBC2ED35C154ADD0 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */,
|
||||
3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */,
|
||||
020F7E70167FB2833266F2F0 /* AnalyticsSettingsScreen.swift in Sources */,
|
||||
95690DDD9D547D3D842ACBE3 /* AnalyticsSettingsScreenCoordinator.swift in Sources */,
|
||||
@ -5812,8 +5891,6 @@
|
||||
8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */,
|
||||
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */,
|
||||
8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */,
|
||||
B09DC6E3D0EE87C4D4ABFAB3 /* EncryptedHistoryRoomTimelineItem.swift in Sources */,
|
||||
9965CB800CE6BC74ACA969FC /* EncryptedHistoryRoomTimelineView.swift in Sources */,
|
||||
4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */,
|
||||
B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */,
|
||||
FBD402E3170EB1ED0D1AA672 /* EncryptionKeyProvider.swift in Sources */,
|
||||
@ -5850,9 +5927,18 @@
|
||||
B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */,
|
||||
0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */,
|
||||
A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */,
|
||||
584590D0EA548152A393E72C /* HomeScreenSessionVerificationBanner.swift in Sources */,
|
||||
DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */,
|
||||
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */,
|
||||
2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */,
|
||||
C3BB6887CF13B19182E81F87 /* IdentityConfirmationScreenCoordinator.swift in Sources */,
|
||||
77574A519A4E484880053EAD /* IdentityConfirmationScreenModels.swift in Sources */,
|
||||
0C346A4AD174F441EDB1414E /* IdentityConfirmationScreenViewModel.swift in Sources */,
|
||||
489BB6A733D3DA0FE7062650 /* IdentityConfirmationScreenViewModelProtocol.swift in Sources */,
|
||||
9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */,
|
||||
93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */,
|
||||
D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */,
|
||||
01681E8B20AD6F0D237F2DC1 /* IdentityConfirmedScreenViewModel.swift in Sources */,
|
||||
AADE7C2497A7B55D8BED7BD6 /* IdentityConfirmedScreenViewModelProtocol.swift in Sources */,
|
||||
BA31448FBD9697F8CB9A83CD /* ImageCache.swift in Sources */,
|
||||
85813D87DDD7F67A46BD9AF7 /* ImageProviderProtocol.swift in Sources */,
|
||||
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */,
|
||||
@ -5970,6 +6056,11 @@
|
||||
652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */,
|
||||
06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */,
|
||||
C4C84901ABAC9B17564AB7EB /* NotificationName.swift in Sources */,
|
||||
5139F4BD5A5DF6F8D11A9BDE /* NotificationPermissionsScreen.swift in Sources */,
|
||||
454311EAC17D778E19F46592 /* NotificationPermissionsScreenCoordinator.swift in Sources */,
|
||||
3E7B65C2C97748D5D65AAA8B /* NotificationPermissionsScreenModels.swift in Sources */,
|
||||
D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */,
|
||||
C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */,
|
||||
C0090506A52A1991BAF4BA68 /* NotificationSettingsChatType.swift in Sources */,
|
||||
AA93B3F9B5DD097DEF79F981 /* NotificationSettingsEditScreen.swift in Sources */,
|
||||
53A59720F4729D9BBFFB7CAB /* NotificationSettingsEditScreenCoordinator.swift in Sources */,
|
||||
@ -5987,6 +6078,7 @@
|
||||
CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */,
|
||||
523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */,
|
||||
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */,
|
||||
11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */,
|
||||
3CE4C5071B6D2576E2473989 /* OrderedSet.swift in Sources */,
|
||||
AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */,
|
||||
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */,
|
||||
@ -6139,7 +6231,7 @@
|
||||
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */,
|
||||
77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */,
|
||||
B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */,
|
||||
D8385A51A3D0FA9283556281 /* RoundedLabelItem.swift in Sources */,
|
||||
BD11E639CF566A9DA8FCA717 /* RoundedLabelItem.swift in Sources */,
|
||||
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */,
|
||||
D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */,
|
||||
F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */,
|
||||
@ -6187,12 +6279,12 @@
|
||||
237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */,
|
||||
AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */,
|
||||
94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */,
|
||||
7A0A0929556792FB19B812C5 /* SessionVerificationScreen.swift in Sources */,
|
||||
E9F148072F9513EC2272AA21 /* SessionVerificationScreenCoordinator.swift in Sources */,
|
||||
5770C4906668C6D3008A2AC9 /* SessionVerificationScreenModels.swift in Sources */,
|
||||
B27D3190784F85916DA1C394 /* SessionVerificationScreenStateMachine.swift in Sources */,
|
||||
F4433EF57B4BB3C077F8B00E /* SessionVerificationScreenViewModel.swift in Sources */,
|
||||
E570117376826665640F0CFD /* SessionVerificationScreenViewModelProtocol.swift in Sources */,
|
||||
707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */,
|
||||
D02DEB36D32A72A1B365E452 /* SessionVerificationScreenCoordinator.swift in Sources */,
|
||||
5710AAB27D5D866292C1FE06 /* SessionVerificationScreenModels.swift in Sources */,
|
||||
601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */,
|
||||
4A8287E5281B44A8754BE509 /* SessionVerificationScreenViewModel.swift in Sources */,
|
||||
762DB0973865293F0C3D3D7B /* SessionVerificationScreenViewModelProtocol.swift in Sources */,
|
||||
755395927DDD6EBDDA5E217A /* SettingsFlowCoordinator.swift in Sources */,
|
||||
34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */,
|
||||
AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */,
|
||||
@ -6737,7 +6829,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.3;
|
||||
MARKETING_VERSION = 1.5.13;
|
||||
MARKETING_VERSION = 1.6.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@ -6813,7 +6905,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.3;
|
||||
MARKETING_VERSION = 1.5.13;
|
||||
MARKETING_VERSION = 1.6.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
|
22
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/Contents.json
vendored
Normal file
22
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "background-bottom-light.png",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "background-bottom-dark.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/background-bottom-dark.png
vendored
Normal file
BIN
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/background-bottom-dark.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
BIN
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/background-bottom-light.png
vendored
Normal file
BIN
ElementX/Resources/Assets.xcassets/images/background-bottom.imageset/background-bottom-light.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
57
ElementX/Resources/Assets.xcassets/images/notifications-prompt-graphic.imageset/Alerts.svg
vendored
Normal file
57
ElementX/Resources/Assets.xcassets/images/notifications-prompt-graphic.imageset/Alerts.svg
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<svg width="393" height="272" viewBox="0 0 393 272" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_1_4123)">
|
||||
<rect x="15" y="20" width="361" height="64" rx="14" fill="white" shape-rendering="crispEdges"/>
|
||||
<rect x="15.75" y="20.75" width="359.5" height="62.5" rx="13.25" stroke="#F7F9FA" stroke-width="1.5" shape-rendering="crispEdges"/>
|
||||
<rect x="31" y="36" width="32" height="32" rx="16" fill="#E0F8D9"/>
|
||||
<path d="M40.3818 58.5V45.8174H43.4141L46.9297 55.0986H47.0791L50.5859 45.8174H53.627V58.5H51.2627V49.8691H49.9619L52.4932 46.1689L47.835 58.5H46.165L41.5156 46.1689L44.0469 49.8691H42.7461V58.5H40.3818Z" fill="#005F00"/>
|
||||
<rect x="79" y="40" width="220" height="8" rx="4" fill="#052E61" fill-opacity="0.12"/>
|
||||
<rect x="79" y="56" width="100" height="8" rx="4" fill="#052E61" fill-opacity="0.12"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d_1_4123)">
|
||||
<rect x="15" y="100" width="361" height="64" rx="14" fill="white" shape-rendering="crispEdges"/>
|
||||
<rect x="15.75" y="100.75" width="359.5" height="62.5" rx="13.25" stroke="#F7F9FA" stroke-width="1.5" shape-rendering="crispEdges"/>
|
||||
<rect x="31" y="116" width="32" height="32" rx="16" fill="#FAEEFB"/>
|
||||
<path d="M41.041 138.5L45.4443 125.817H47.7119V128.349H46.9297L43.8271 138.5H41.041ZM43.3965 135.424L44.0469 133.438H49.9092L50.5596 135.424H43.3965ZM50.1816 138.5L47.0791 128.349V125.817H48.5645L52.9766 138.5H50.1816Z" fill="#822198"/>
|
||||
<rect x="79" y="120" width="219" height="8" rx="4" fill="#052E61" fill-opacity="0.12"/>
|
||||
<rect x="79" y="136" width="219" height="8" rx="4" fill="#052E61" fill-opacity="0.12"/>
|
||||
</g>
|
||||
<g filter="url(#filter2_d_1_4123)">
|
||||
<rect x="15" y="180" width="361" height="64" rx="14" fill="white" shape-rendering="crispEdges"/>
|
||||
<rect x="15.75" y="180.75" width="359.5" height="62.5" rx="13.25" stroke="#F7F9FA" stroke-width="1.5" shape-rendering="crispEdges"/>
|
||||
<rect x="31" y="196" width="32" height="32" rx="16" fill="#FFEFE4"/>
|
||||
<path d="M45.6641 218.5V208.006H41.8672V205.817H52.124V208.006H48.3184V218.5H45.6641Z" fill="#9B2200"/>
|
||||
<rect x="79" y="208" width="154" height="8" rx="4" fill="#052E61" fill-opacity="0.12"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_1_4123" x="-9" y="0" width="409" height="112" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="12"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.105882 0 0 0 0 0.113725 0 0 0 0 0.133333 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_4123"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_4123" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_1_4123" x="-9" y="80" width="409" height="112" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="12"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.105882 0 0 0 0 0.113725 0 0 0 0 0.133333 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_4123"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_4123" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter2_d_1_4123" x="-9" y="160" width="409" height="112" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="4"/>
|
||||
<feGaussianBlur stdDeviation="12"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.105882 0 0 0 0 0.113725 0 0 0 0 0.133333 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_4123"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_4123" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
15
ElementX/Resources/Assets.xcassets/images/notifications-prompt-graphic.imageset/Contents.json
vendored
Normal file
15
ElementX/Resources/Assets.xcassets/images/notifications-prompt-graphic.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Alerts.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true
|
||||
}
|
||||
}
|
@ -398,6 +398,10 @@
|
||||
"screen_edit_profile_error_title" = "Unable to update profile";
|
||||
"screen_edit_profile_title" = "Edit profile";
|
||||
"screen_edit_profile_updating_details" = "Updating profile…";
|
||||
"screen_identity_confirmation_subtitle" = "Verify this device to set up secure messaging.";
|
||||
"screen_identity_confirmation_title" = "Confirm that it's you";
|
||||
"screen_identity_confirmed_subtitle" = "Now you can read or send messages securely, and anyone you chat with can also trust this device.";
|
||||
"screen_identity_confirmed_title" = "Device verified";
|
||||
"screen_invites_decline_chat_message" = "Are you sure you want to decline the invitation to join %1$@?";
|
||||
"screen_invites_decline_chat_title" = "Decline invite";
|
||||
"screen_invites_decline_direct_chat_message" = "Are you sure you want to decline this private chat with %1$@?";
|
||||
|
@ -83,7 +83,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
MXLog.info("\(appName) \(appVersion) (\(appBuild))")
|
||||
|
||||
if ProcessInfo.processInfo.environment["RESET_APP_SETTINGS"].map(Bool.init) == true {
|
||||
AppSettings.reset()
|
||||
AppSettings.resetAllSettings()
|
||||
}
|
||||
|
||||
self.appDelegate = appDelegate
|
||||
@ -154,12 +154,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
return
|
||||
}
|
||||
|
||||
if appSettings.appLockIsMandatory, !appLockFlowCoordinator.appLockService.isEnabled {
|
||||
stateMachine.processEvent(.startWithAppLockSetup)
|
||||
} else {
|
||||
stateMachine.processEvent(.startWithExistingSession)
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
hideLoadingIndicator()
|
||||
@ -319,13 +315,21 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
appSettings.migratedAccounts[userID] = true
|
||||
}
|
||||
}
|
||||
|
||||
if oldVersion < Version(1, 6, 0) {
|
||||
MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.")
|
||||
if !userSessionStore.userIDs.isEmpty {
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
appSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the keychain, app support directory etc ready for a fresh use.
|
||||
/// - Parameter includingSettings: Whether to additionally wipe the user's app settings too.
|
||||
private func wipeUserData(includingSettings: Bool = false) {
|
||||
if includingSettings {
|
||||
AppSettings.reset()
|
||||
AppSettings.resetAllSettings()
|
||||
appLockFlowCoordinator.appLockService.disable()
|
||||
}
|
||||
userSessionStore.reset()
|
||||
@ -339,19 +343,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
case (.initial, .startWithAuthentication, .signedOut):
|
||||
startAuthentication()
|
||||
case (.signedOut, .createdUserSession, .signedIn):
|
||||
setupUserSession()
|
||||
setupUserSession(isNewLogin: true)
|
||||
case (.initial, .startWithExistingSession, .restoringSession):
|
||||
restoreUserSession()
|
||||
case (.restoringSession, .failedRestoringSession, .signedOut):
|
||||
showLoginErrorToast()
|
||||
presentSplashScreen()
|
||||
case (.restoringSession, .createdUserSession, .signedIn):
|
||||
setupUserSession()
|
||||
|
||||
case (.initial, .startWithAppLockSetup, .mandatoryAppLockSetup):
|
||||
startMandatoryAppLockSetup()
|
||||
case (.mandatoryAppLockSetup, .appLockSetupComplete, .restoringSession):
|
||||
restoreUserSession()
|
||||
setupUserSession(isNewLogin: false)
|
||||
|
||||
case (.signingOut, .signOut, .signingOut):
|
||||
// We can ignore signOut when already in the process of signing out,
|
||||
@ -397,7 +396,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
encryptionKeyProvider: EncryptionKeyProvider(),
|
||||
appSettings: appSettings)
|
||||
authenticationFlowCoordinator = AuthenticationFlowCoordinator(authenticationService: authenticationService,
|
||||
appLockService: appLockFlowCoordinator.appLockService,
|
||||
bugReportService: ServiceLocator.shared.bugReportService,
|
||||
navigationRootCoordinator: navigationRootCoordinator,
|
||||
appSettings: appSettings,
|
||||
@ -450,7 +448,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
}
|
||||
}
|
||||
|
||||
private func setupUserSession() {
|
||||
private func setupUserSession(isNewLogin: Bool) {
|
||||
guard let userSession else {
|
||||
fatalError("User session not setup")
|
||||
}
|
||||
@ -462,9 +460,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
bugReportService: ServiceLocator.shared.bugReportService,
|
||||
roomTimelineControllerFactory: RoomTimelineControllerFactory(),
|
||||
appSettings: appSettings,
|
||||
analytics: ServiceLocator.shared.analytics)
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
notificationManager: notificationManager,
|
||||
isNewLogin: isNewLogin)
|
||||
|
||||
userSessionFlowCoordinator.actions
|
||||
userSessionFlowCoordinator.actionsPublisher
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
@ -488,31 +488,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to add a PIN code to an existing session that somehow missed out mandatory PIN setup.
|
||||
private func startMandatoryAppLockSetup() {
|
||||
MXLog.info("Mandatory App Lock enabled but no PIN is set. Showing the setup flow.")
|
||||
|
||||
let navigationCoordinator = NavigationStackCoordinator()
|
||||
let coordinator = AppLockSetupFlowCoordinator(presentingFlow: .onboarding,
|
||||
appLockService: appLockFlowCoordinator.appLockService,
|
||||
navigationStackCoordinator: navigationCoordinator)
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .complete:
|
||||
stateMachine.processEvent(.appLockSetupComplete)
|
||||
appLockSetupFlowCoordinator = nil
|
||||
case .forceLogout:
|
||||
fatalError("Creating a PIN shouldn't be able to fail in this way")
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
appLockSetupFlowCoordinator = coordinator
|
||||
navigationRootCoordinator.setRootCoordinator(navigationCoordinator)
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func logout(isSoft: Bool) {
|
||||
guard let userSession else {
|
||||
fatalError("User session not setup")
|
||||
@ -544,6 +519,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
userSessionStore.logout(userSession: userSession)
|
||||
tearDownUserSession()
|
||||
|
||||
AppSettings.resetSessionSpecificSettings()
|
||||
|
||||
// Reset analytics
|
||||
ServiceLocator.shared.analytics.optOut()
|
||||
ServiceLocator.shared.analytics.resetConsentState()
|
||||
@ -591,7 +568,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
private func configureNotificationManager() {
|
||||
notificationManager.setUserSession(userSession)
|
||||
notificationManager.requestAuthorization()
|
||||
|
||||
appDelegateObserver = appDelegate.callbacks
|
||||
.receive(on: DispatchQueue.main)
|
||||
@ -689,7 +665,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
// MARK: Toasts and loading indicators
|
||||
|
||||
private static let loadingIndicatorIdentifier = "AppCoordinatorLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(AppCoordinator.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -29,11 +29,6 @@ class AppCoordinatorStateMachine {
|
||||
/// Opening an existing session.
|
||||
case restoringSession
|
||||
|
||||
/// Showing the mandatory app lock setup flow before restoring the session.
|
||||
/// This state should only be allowed before restoring an existing session. For
|
||||
/// new users the setup is inserted in the middle of the authentication flow.
|
||||
case mandatoryAppLockSetup
|
||||
|
||||
/// User session started
|
||||
case signedIn
|
||||
|
||||
@ -49,20 +44,12 @@ class AppCoordinatorStateMachine {
|
||||
/// Start the `AppCoordinator` by restoring an existing account.
|
||||
case startWithExistingSession
|
||||
|
||||
/// Start the `AppCoordinator` by showing the mandatory PIN creation flow.
|
||||
/// This event should only be sent if an account exists and a mandatory PIN is
|
||||
/// missing. Normally it will be handled as part of the authentication flow.
|
||||
case startWithAppLockSetup
|
||||
|
||||
/// Restoring session failed.
|
||||
case failedRestoringSession
|
||||
|
||||
/// A session has been created.
|
||||
case createdUserSession
|
||||
|
||||
/// The app lock setup has been completed.
|
||||
case appLockSetupComplete
|
||||
|
||||
/// Request sign out.
|
||||
case signOut(isSoft: Bool, disableAppLock: Bool)
|
||||
/// Request the soft logout screen.
|
||||
@ -93,9 +80,6 @@ class AppCoordinatorStateMachine {
|
||||
stateMachine.addRoutes(event: .createdUserSession, transitions: [.restoringSession => .signedIn])
|
||||
stateMachine.addRoutes(event: .failedRestoringSession, transitions: [.restoringSession => .signedOut])
|
||||
|
||||
stateMachine.addRoutes(event: .startWithAppLockSetup, transitions: [.initial => .mandatoryAppLockSetup])
|
||||
stateMachine.addRoutes(event: .appLockSetupComplete, transitions: [.mandatoryAppLockSetup => .restoringSession])
|
||||
|
||||
stateMachine.addRoutes(event: .completedSigningOut, transitions: [.signingOut(isSoft: false, disableAppLock: false) => .signedOut,
|
||||
.signingOut(isSoft: false, disableAppLock: true) => .signedOut])
|
||||
stateMachine.addRoutes(event: .showSoftLogout, transitions: [.signingOut(isSoft: true, disableAppLock: false) => .softLogout])
|
||||
|
@ -24,10 +24,13 @@ final class AppSettings {
|
||||
case seenInvites
|
||||
case appLockNumberOfPINAttempts
|
||||
case appLockNumberOfBiometricAttempts
|
||||
case lastLoginDate
|
||||
case migratedAccounts
|
||||
case timelineStyle
|
||||
|
||||
case analyticsConsentState
|
||||
case hasRunNotificationPermissionsOnboarding
|
||||
case hasRunIdentityConfirmationOnboarding
|
||||
|
||||
case enableNotifications
|
||||
case enableInAppNotifications
|
||||
case pusherProfileTag
|
||||
@ -59,11 +62,16 @@ final class AppSettings {
|
||||
|
||||
#if IS_MAIN_APP
|
||||
|
||||
static func reset() {
|
||||
static func resetAllSettings() {
|
||||
MXLog.warning("Resetting the AppSettings.")
|
||||
store.removePersistentDomain(forName: suiteName)
|
||||
}
|
||||
|
||||
static func resetSessionSpecificSettings() {
|
||||
MXLog.warning("Resetting the user session specific AppSettings.")
|
||||
store.removeObject(forKey: UserDefaultsKeys.hasRunIdentityConfirmationOnboarding.rawValue)
|
||||
}
|
||||
|
||||
static func configureWithSuiteName(_ name: String) {
|
||||
suiteName = name
|
||||
|
||||
@ -120,7 +128,9 @@ final class AppSettings {
|
||||
let privacyURL: URL = "https://element.io/privacy"
|
||||
/// An email address that should be used for support requests.
|
||||
let supportEmailAddress = "support@element.io"
|
||||
// A URL where users can go read more about the chat backup.
|
||||
/// A URL where users can go read more about encryption in general.
|
||||
let encryptionURL: URL = "https://element.io/help#encryption"
|
||||
/// A URL where users can go read more about the chat backup.
|
||||
let chatBackupDetailsURL: URL = "https://element.io/help#encryption5"
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.appAppearance, defaultValue: .system, storageType: .userDefaults(store))
|
||||
@ -154,13 +164,6 @@ final class AppSettings {
|
||||
return url
|
||||
}()
|
||||
|
||||
/// The date that the call to `/login` completed successfully. This is used to put
|
||||
/// a hard wall on the history of encrypted messages until we have key backup.
|
||||
///
|
||||
/// Not a multi-account aware setting as key backup will come before multi-account.
|
||||
@UserPreference(key: UserDefaultsKeys.lastLoginDate, defaultValue: nil, storageType: .userDefaults(store))
|
||||
var lastLoginDate: Date?
|
||||
|
||||
/// A dictionary of accounts that have performed an initial sync through their proxy.
|
||||
///
|
||||
/// This is a temporary workaround. In the future we should be able to receive a signal from the
|
||||
@ -211,6 +214,12 @@ final class AppSettings {
|
||||
@UserPreference(key: UserDefaultsKeys.analyticsConsentState, defaultValue: AnalyticsConsentState.unknown, storageType: .userDefaults(store))
|
||||
var analyticsConsentState
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hasRunNotificationPermissionsOnboarding, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hasRunNotificationPermissionsOnboarding
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hasRunIdentityConfirmationOnboarding, defaultValue: false, storageType: .userDefaults(store))
|
||||
var hasRunIdentityConfirmationOnboarding
|
||||
|
||||
// MARK: - Home Screen
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.hideUnreadMessagesBadge, defaultValue: false, storageType: .userDefaults(store))
|
||||
|
@ -24,7 +24,6 @@ protocol AuthenticationFlowCoordinatorDelegate: AnyObject {
|
||||
|
||||
class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let authenticationService: AuthenticationServiceProxyProtocol
|
||||
private let appLockService: AppLockServiceProtocol
|
||||
private let bugReportService: BugReportServiceProtocol
|
||||
private let navigationRootCoordinator: NavigationRootCoordinator
|
||||
private let navigationStackCoordinator: NavigationStackCoordinator
|
||||
@ -36,23 +35,18 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private var oidcPresenter: OIDCAuthenticationPresenter?
|
||||
|
||||
// periphery: ignore - used to store the coordinator to avoid deallocation
|
||||
private var appLockFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
|
||||
|
||||
weak var delegate: AuthenticationFlowCoordinatorDelegate?
|
||||
|
||||
init(authenticationService: AuthenticationServiceProxyProtocol,
|
||||
appLockService: AppLockServiceProtocol,
|
||||
bugReportService: BugReportServiceProtocol,
|
||||
navigationRootCoordinator: NavigationRootCoordinator,
|
||||
appSettings: AppSettings,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.authenticationService = authenticationService
|
||||
self.appLockService = appLockService
|
||||
self.bugReportService = bugReportService
|
||||
self.navigationRootCoordinator = navigationRootCoordinator
|
||||
self.appSettings = appSettings
|
||||
@ -108,7 +102,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private func showReportProblemScreen() {
|
||||
bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .sheet(navigationStackCoordinator),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
userIndicatorController: userIndicatorController,
|
||||
bugReportService: bugReportService,
|
||||
userID: nil,
|
||||
deviceID: nil))
|
||||
@ -265,58 +259,10 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
|
||||
private func userHasSignedIn(userSession: UserSessionProtocol) {
|
||||
appSettings.lastLoginDate = .now
|
||||
|
||||
if appSettings.appLockIsMandatory, !appLockService.isEnabled {
|
||||
showAppLockSetupFlow(userSession: userSession)
|
||||
} else if analytics.shouldShowAnalyticsPrompt {
|
||||
showAnalyticsPrompt(userSession: userSession)
|
||||
} else {
|
||||
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
}
|
||||
|
||||
private func showAppLockSetupFlow(userSession: UserSessionProtocol) {
|
||||
let coordinator = AppLockSetupFlowCoordinator(presentingFlow: .onboarding,
|
||||
appLockService: appLockService,
|
||||
navigationStackCoordinator: navigationStackCoordinator)
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .complete:
|
||||
appLockFlowCoordinator = nil
|
||||
if analytics.shouldShowAnalyticsPrompt {
|
||||
showAnalyticsPrompt(userSession: userSession)
|
||||
} else {
|
||||
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
case .forceLogout:
|
||||
fatalError("The PIN creation flow should not fail.")
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
appLockFlowCoordinator = coordinator
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func showAnalyticsPrompt(userSession: UserSessionProtocol) {
|
||||
let coordinator = AnalyticsPromptScreenCoordinator(analytics: analytics, termsURL: appSettings.analyticsConfiguration.termsURL)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .done:
|
||||
delegate?.authenticationFlowCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
navigationStackCoordinator.push(coordinator)
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "authenticationFlowCoordinatorLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(AuthenticationFlowCoordinator.self)-Loading"
|
||||
|
||||
private func startLoading() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -0,0 +1,343 @@
|
||||
//
|
||||
// Copyright 2024 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 Foundation
|
||||
import SwiftState
|
||||
|
||||
class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let userSession: UserSessionProtocol
|
||||
private let appLockService: AppLockServiceProtocol
|
||||
private let analyticsService: AnalyticsService
|
||||
private let appSettings: AppSettings
|
||||
private let notificationManager: NotificationManagerProtocol
|
||||
private let rootNavigationStackCoordinator: NavigationStackCoordinator
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let isNewLogin: Bool
|
||||
|
||||
private var navigationStackCoordinator: NavigationStackCoordinator!
|
||||
|
||||
enum State: StateType {
|
||||
case initial
|
||||
case identityConfirmation
|
||||
case identityConfirmed
|
||||
case appLockSetup
|
||||
case analyticsPrompt
|
||||
case notificationPermissions
|
||||
case finished
|
||||
}
|
||||
|
||||
enum Event: EventType {
|
||||
case next
|
||||
}
|
||||
|
||||
private let stateMachine: StateMachine<State, Event>
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
// periphery: ignore - used to store the coordinator to avoid deallocation
|
||||
private var appLockFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||
|
||||
init(userSession: UserSessionProtocol,
|
||||
appLockService: AppLockServiceProtocol,
|
||||
analyticsService: AnalyticsService,
|
||||
appSettings: AppSettings,
|
||||
notificationManager: NotificationManagerProtocol,
|
||||
navigationStackCoordinator: NavigationStackCoordinator,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
isNewLogin: Bool) {
|
||||
self.userSession = userSession
|
||||
self.appLockService = appLockService
|
||||
self.analyticsService = analyticsService
|
||||
self.appSettings = appSettings
|
||||
self.notificationManager = notificationManager
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.isNewLogin = isNewLogin
|
||||
|
||||
rootNavigationStackCoordinator = navigationStackCoordinator
|
||||
self.navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
stateMachine = .init(state: .initial)
|
||||
}
|
||||
|
||||
var shouldStart: Bool {
|
||||
guard stateMachine.state == .initial, !ProcessInfo.isRunningIntegrationTests else {
|
||||
return false
|
||||
}
|
||||
|
||||
return isNewLogin || requiresVerification || requiresAppLockSetup || requiresAnalyticsSetup || requiresNotificationsSetup
|
||||
}
|
||||
|
||||
func start() {
|
||||
guard shouldStart else {
|
||||
fatalError("This flow coordinator shouldn't have been started")
|
||||
}
|
||||
|
||||
configureStateMachine()
|
||||
|
||||
stateMachine.tryEvent(.next)
|
||||
|
||||
rootNavigationStackCoordinator.setFullScreenCoverCoordinator(navigationStackCoordinator, animated: !isNewLogin)
|
||||
}
|
||||
|
||||
func handleAppRoute(_ appRoute: AppRoute, animated: Bool) {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
func clearRoute(animated: Bool) {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var requiresVerification: Bool {
|
||||
// We want to make sure onboarding finishes but also every time the user becomes unverified (e.g. account reset)
|
||||
!appSettings.hasRunIdentityConfirmationOnboarding || userSession.sessionSecurityStatePublisher.value.verificationState == .unverified
|
||||
}
|
||||
|
||||
private var requiresAppLockSetup: Bool {
|
||||
appSettings.appLockIsMandatory && !appLockService.isEnabled
|
||||
}
|
||||
|
||||
private var requiresAnalyticsSetup: Bool {
|
||||
analyticsService.shouldShowAnalyticsPrompt
|
||||
}
|
||||
|
||||
private var requiresNotificationsSetup: Bool {
|
||||
!appSettings.hasRunNotificationPermissionsOnboarding
|
||||
}
|
||||
|
||||
private func configureStateMachine() {
|
||||
stateMachine.addRouteMapping { [weak self] _, fromState, _ in
|
||||
guard let self else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch (fromState, requiresVerification, requiresAppLockSetup, requiresAnalyticsSetup, requiresNotificationsSetup) {
|
||||
case (.initial, true, _, _, _):
|
||||
return .identityConfirmation
|
||||
case (.initial, false, true, _, _):
|
||||
return .appLockSetup
|
||||
case (.initial, false, false, true, _):
|
||||
return .analyticsPrompt
|
||||
case (.initial, false, false, false, true):
|
||||
return .notificationPermissions
|
||||
|
||||
case (.identityConfirmation, _, _, _, _):
|
||||
return .identityConfirmed
|
||||
|
||||
case (.identityConfirmed, _, true, _, _):
|
||||
return .appLockSetup
|
||||
case (.identityConfirmed, _, false, true, _):
|
||||
return .analyticsPrompt
|
||||
case (.identityConfirmed, _, false, false, true):
|
||||
return .notificationPermissions
|
||||
case (.identityConfirmed, _, false, false, false):
|
||||
return .finished
|
||||
|
||||
case (.appLockSetup, _, _, true, _):
|
||||
return .analyticsPrompt
|
||||
case (.appLockSetup, _, _, false, true):
|
||||
return .notificationPermissions
|
||||
case (.appLockSetup, _, _, false, false):
|
||||
return .finished
|
||||
|
||||
case (.analyticsPrompt, _, _, _, true):
|
||||
return .notificationPermissions
|
||||
case (.analyticsPrompt, _, _, _, false):
|
||||
return .finished
|
||||
|
||||
case (.notificationPermissions, _, _, _, _):
|
||||
return .finished
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
stateMachine.addAnyHandler(.any => .any) { [weak self] context in
|
||||
guard let self else { return }
|
||||
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (_, _, .identityConfirmation):
|
||||
presentIdentityConfirmationScreen()
|
||||
case (_, _, .identityConfirmed):
|
||||
presentIdentityConfirmedScreen()
|
||||
case (_, _, .appLockSetup):
|
||||
presentAppLockSetupFlow()
|
||||
case (_, _, .analyticsPrompt):
|
||||
presentAnalyticsPromptScreen()
|
||||
case (_, _, .notificationPermissions):
|
||||
presentNotificationPermissionsScreen()
|
||||
case (_, _, .finished):
|
||||
rootNavigationStackCoordinator.setFullScreenCoverCoordinator(nil)
|
||||
default:
|
||||
fatalError("Unknown transition: \(context)")
|
||||
}
|
||||
}
|
||||
|
||||
stateMachine.addErrorHandler { context in
|
||||
fatalError("Unexpected transition: \(context)")
|
||||
}
|
||||
}
|
||||
|
||||
private func presentIdentityConfirmationScreen() {
|
||||
let parameters = IdentityConfirmationScreenCoordinatorParameters(userSession: userSession,
|
||||
appSettings: appSettings,
|
||||
userIndicatorController: userIndicatorController)
|
||||
|
||||
let coordinator = IdentityConfirmationScreenCoordinator(parameters: parameters)
|
||||
coordinator.actionsPublisher.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .otherDevice:
|
||||
Task {
|
||||
await self.presentSessionVerificationScreen()
|
||||
}
|
||||
case .recoveryKey:
|
||||
presentRecoveryKeyScreen()
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentSessionVerificationScreen() async {
|
||||
guard case let .success(sessionVerificationController) = await userSession.clientProxy.sessionVerificationControllerProxy() else {
|
||||
fatalError("The sessionVerificationController should aways be valid at this point")
|
||||
}
|
||||
|
||||
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController)
|
||||
|
||||
let coordinator = SessionVerificationScreenCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .done:
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
stateMachine.tryEvent(.next)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentRecoveryKeyScreen() {
|
||||
let parameters = SecureBackupRecoveryKeyScreenCoordinatorParameters(secureBackupController: userSession.clientProxy.secureBackupController,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
isModallyPresented: false)
|
||||
|
||||
let coordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .recoveryFixed:
|
||||
appSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
stateMachine.tryEvent(.next)
|
||||
default:
|
||||
fatalError("Other flows shouldn't be possible")
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentIdentityConfirmedScreen() {
|
||||
let coordinator = IdentityConfirmedScreenCoordinator(parameters: .init())
|
||||
coordinator.actionsPublisher
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .done:
|
||||
stateMachine.tryEvent(.next)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentAppLockSetupFlow() {
|
||||
let coordinator = AppLockSetupFlowCoordinator(presentingFlow: .onboarding,
|
||||
appLockService: appLockService,
|
||||
navigationStackCoordinator: navigationStackCoordinator)
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .complete:
|
||||
appLockFlowCoordinator = nil
|
||||
stateMachine.tryEvent(.next)
|
||||
case .forceLogout:
|
||||
fatalError("The PIN creation flow should not fail.")
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
appLockFlowCoordinator = coordinator
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func presentAnalyticsPromptScreen() {
|
||||
let coordinator = AnalyticsPromptScreenCoordinator(analytics: analyticsService, termsURL: appSettings.analyticsConfiguration.termsURL)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .done:
|
||||
stateMachine.tryEvent(.next)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentNotificationPermissionsScreen() {
|
||||
let coordinator = NotificationPermissionsScreenCoordinator(parameters: .init(notificationManager: notificationManager))
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .done:
|
||||
appSettings.hasRunNotificationPermissionsOnboarding = true
|
||||
stateMachine.tryEvent(.next)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
presentCoordinator(coordinator)
|
||||
}
|
||||
|
||||
private func presentCoordinator(_ coordinator: CoordinatorProtocol) {
|
||||
if navigationStackCoordinator.rootCoordinator == nil {
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||
} else {
|
||||
navigationStackCoordinator.push(coordinator)
|
||||
}
|
||||
}
|
||||
}
|
@ -434,8 +434,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
||||
|
||||
let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
||||
timelineItemFactory: timelineItemFactory,
|
||||
secureBackupController: userSession.clientProxy.secureBackupController)
|
||||
timelineItemFactory: timelineItemFactory)
|
||||
self.timelineController = timelineController
|
||||
|
||||
analytics.trackViewRoom(isDM: roomProxy.isDirect, isSpace: roomProxy.isSpace)
|
||||
@ -918,8 +917,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
||||
|
||||
let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
||||
timelineItemFactory: timelineItemFactory,
|
||||
secureBackupController: userSession.clientProxy.secureBackupController)
|
||||
timelineItemFactory: timelineItemFactory)
|
||||
|
||||
let parameters = RoomPollsHistoryScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||
pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy),
|
||||
|
@ -130,10 +130,6 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
presentLegalInformationScreen()
|
||||
case .blockedUsers:
|
||||
presentBlockedUsersScreen()
|
||||
case .sessionVerification:
|
||||
Task {
|
||||
await self.presentSessionVerificationScreen()
|
||||
}
|
||||
case .accountSessions:
|
||||
presentAccountSessionsListURL()
|
||||
case .notifications:
|
||||
@ -213,34 +209,6 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
navigationStackCoordinator.push(coordinator)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
let verificationParameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController,
|
||||
recoveryState: parameters.userSession.sessionSecurityStatePublisher.value.recoveryState)
|
||||
let coordinator = SessionVerificationScreenCoordinator(parameters: verificationParameters)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .recoveryKey:
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
handleAppRoute(.chatBackupSettings, animated: true)
|
||||
case .done:
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in
|
||||
self?.navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func presentNotificationSettings() {
|
||||
let notificationParameters = NotificationSettingsScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
|
||||
userSession: parameters.userSession,
|
||||
|
@ -31,7 +31,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let windowManager: WindowManagerProtocol
|
||||
private let bugReportService: BugReportServiceProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let actionsSubject: PassthroughSubject<UserSessionFlowCoordinatorAction, Never> = .init()
|
||||
|
||||
private let stateMachine: UserSessionFlowCoordinatorStateMachine
|
||||
|
||||
@ -39,6 +38,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private let settingsFlowCoordinator: SettingsFlowCoordinator
|
||||
|
||||
private let onboardingFlowCoordinator: OnboardingFlowCoordinator
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
|
||||
|
||||
@ -52,7 +53,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private let selectedRoomSubject = CurrentValueSubject<String?, Never>(nil)
|
||||
|
||||
var actions: AnyPublisher<UserSessionFlowCoordinatorAction, Never> {
|
||||
private let actionsSubject: PassthroughSubject<UserSessionFlowCoordinatorAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<UserSessionFlowCoordinatorAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
@ -63,7 +65,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
bugReportService: BugReportServiceProtocol,
|
||||
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol,
|
||||
appSettings: AppSettings,
|
||||
analytics: AnalyticsService) {
|
||||
analytics: AnalyticsService,
|
||||
notificationManager: NotificationManagerProtocol,
|
||||
isNewLogin: Bool) {
|
||||
stateMachine = UserSessionFlowCoordinatorStateMachine()
|
||||
self.userSession = userSession
|
||||
self.navigationRootCoordinator = navigationRootCoordinator
|
||||
@ -98,8 +102,29 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
navigationSplitCoordinator: navigationSplitCoordinator,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
||||
|
||||
onboardingFlowCoordinator = OnboardingFlowCoordinator(userSession: userSession,
|
||||
appLockService: appLockService,
|
||||
analyticsService: analytics,
|
||||
appSettings: appSettings,
|
||||
notificationManager: notificationManager,
|
||||
navigationStackCoordinator: detailNavigationStackCoordinator,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
isNewLogin: isNewLogin)
|
||||
|
||||
setupStateMachine()
|
||||
|
||||
userSession.sessionSecurityStatePublisher
|
||||
.map(\.verificationState)
|
||||
.filter { $0 != .unknown }
|
||||
.removeDuplicates()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
attemptStartingOnboarding()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
roomFlowCoordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
@ -208,11 +233,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
|
||||
func clearRoute(animated: Bool) {
|
||||
fatalError("not necessary as of right now")
|
||||
roomFlowCoordinator.clearRoute(animated: animated)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
func attemptStartingOnboarding() {
|
||||
if onboardingFlowCoordinator.shouldStart {
|
||||
clearRoute(animated: false)
|
||||
onboardingFlowCoordinator.start()
|
||||
}
|
||||
}
|
||||
|
||||
private func clearPresentedSheets(animated: Bool, completion: @escaping () -> Void) {
|
||||
if navigationSplitCoordinator.sheetCoordinator == nil {
|
||||
completion()
|
||||
@ -234,6 +266,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (.initial, .start, .roomList):
|
||||
presentHomeScreen()
|
||||
attemptStartingOnboarding()
|
||||
|
||||
case(.roomList, .selectRoom, .roomList):
|
||||
break
|
||||
@ -245,13 +278,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case (.invitesScreen, .deselectRoom, .invitesScreen):
|
||||
break
|
||||
|
||||
case (.roomList, .showSessionVerificationScreen, .sessionVerificationScreen):
|
||||
Task {
|
||||
await self.presentSessionVerification(animated: animated)
|
||||
}
|
||||
case (.sessionVerificationScreen, .dismissedSessionVerificationScreen, .roomList):
|
||||
break
|
||||
|
||||
case (.roomList, .showSettingsScreen, .settingsScreen):
|
||||
break
|
||||
case (.settingsScreen, .dismissedSettingsScreen, .roomList):
|
||||
@ -334,8 +360,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
settingsFlowCoordinator.handleAppRoute(.settings, animated: true)
|
||||
case .presentFeedbackScreen:
|
||||
stateMachine.processEvent(.feedbackScreen)
|
||||
case .presentSessionVerificationScreen:
|
||||
stateMachine.processEvent(.showSessionVerificationScreen)
|
||||
case .presentSecureBackupSettings:
|
||||
settingsFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
||||
case .presentStartChatScreen:
|
||||
@ -400,36 +424,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
presentSecureBackupLogoutConfirmationScreen()
|
||||
}
|
||||
|
||||
// MARK: Session verification
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController,
|
||||
recoveryState: userSession.sessionSecurityStatePublisher.value.recoveryState)
|
||||
|
||||
let coordinator = SessionVerificationScreenCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .recoveryKey:
|
||||
settingsFlowCoordinator.handleAppRoute(.chatBackupSettings, animated: true)
|
||||
case .done:
|
||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
navigationSplitCoordinator.setSheetCoordinator(coordinator, animated: animated) { [weak self] in
|
||||
self?.stateMachine.processEvent(.dismissedSessionVerificationScreen)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Start Chat
|
||||
|
||||
private func presentStartChat(animated: Bool) {
|
||||
|
@ -26,9 +26,6 @@ class UserSessionFlowCoordinatorStateMachine {
|
||||
/// Showing the home screen. The `selectedRoomID` represents the timeline shown on the detail panel (if any)
|
||||
case roomList(selectedRoomID: String?)
|
||||
|
||||
/// Showing the session verification flows
|
||||
case sessionVerificationScreen(selectedRoomID: String?)
|
||||
|
||||
/// Showing the session verification flows
|
||||
case feedbackScreen(selectedRoomID: String?)
|
||||
|
||||
@ -70,11 +67,6 @@ class UserSessionFlowCoordinatorStateMachine {
|
||||
/// The feedback screen has been dismissed
|
||||
case dismissedFeedbackScreen
|
||||
|
||||
/// Request the start of the session verification flow
|
||||
case showSessionVerificationScreen
|
||||
/// Session verification has finished
|
||||
case dismissedSessionVerificationScreen
|
||||
|
||||
/// Request the start of the start chat flow
|
||||
case showStartChatScreen
|
||||
/// Start chat has been dismissed
|
||||
@ -126,11 +118,6 @@ class UserSessionFlowCoordinatorStateMachine {
|
||||
case (.feedbackScreen(let selectedRoomID), .dismissedFeedbackScreen):
|
||||
return .roomList(selectedRoomID: selectedRoomID)
|
||||
|
||||
case (.roomList(let selectedRoomID), .showSessionVerificationScreen):
|
||||
return .sessionVerificationScreen(selectedRoomID: selectedRoomID)
|
||||
case (.sessionVerificationScreen(let selectedRoomID), .dismissedSessionVerificationScreen):
|
||||
return .roomList(selectedRoomID: selectedRoomID)
|
||||
|
||||
case (.roomList(let selectedRoomID), .showStartChatScreen):
|
||||
return .startChatScreen(selectedRoomID: selectedRoomID)
|
||||
case (.startChatScreen(let selectedRoomID), .dismissedStartChatScreen):
|
||||
|
@ -33,6 +33,7 @@ internal enum Asset {
|
||||
internal enum Images {
|
||||
internal static let appLogo = ImageAsset(name: "images/app-logo")
|
||||
internal static let serverSelectionIcon = ImageAsset(name: "images/server-selection-icon")
|
||||
internal static let backgroundBottom = ImageAsset(name: "images/background-bottom")
|
||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||
internal static let composerAttachment = ImageAsset(name: "images/composer-attachment")
|
||||
internal static let stopRecording = ImageAsset(name: "images/stop-recording")
|
||||
@ -41,6 +42,7 @@ internal enum Asset {
|
||||
internal static let locationMarkerShape = ImageAsset(name: "images/location-marker-shape")
|
||||
internal static let mediaPause = ImageAsset(name: "images/media-pause")
|
||||
internal static let mediaPlay = ImageAsset(name: "images/media-play")
|
||||
internal static let notificationsPromptGraphic = ImageAsset(name: "images/notifications-prompt-graphic")
|
||||
internal static let waitingGradient = ImageAsset(name: "images/waiting-gradient")
|
||||
}
|
||||
}
|
||||
|
@ -991,6 +991,14 @@ internal enum L10n {
|
||||
internal static var screenEditProfileTitle: String { return L10n.tr("Localizable", "screen_edit_profile_title") }
|
||||
/// Updating profile…
|
||||
internal static var screenEditProfileUpdatingDetails: String { return L10n.tr("Localizable", "screen_edit_profile_updating_details") }
|
||||
/// Verify this device to set up secure messaging.
|
||||
internal static var screenIdentityConfirmationSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_subtitle") }
|
||||
/// Confirm that it's you
|
||||
internal static var screenIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_identity_confirmation_title") }
|
||||
/// Now you can read or send messages securely, and anyone you chat with can also trust this device.
|
||||
internal static var screenIdentityConfirmedSubtitle: String { return L10n.tr("Localizable", "screen_identity_confirmed_subtitle") }
|
||||
/// Device verified
|
||||
internal static var screenIdentityConfirmedTitle: String { return L10n.tr("Localizable", "screen_identity_confirmed_title") }
|
||||
/// Are you sure you want to decline the invitation to join %1$@?
|
||||
internal static func screenInvitesDeclineChatMessage(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "screen_invites_decline_chat_message", String(describing: p1))
|
||||
|
@ -35,9 +35,17 @@ extension ProcessInfo {
|
||||
#endif
|
||||
}
|
||||
|
||||
static var isRunningIntegrationTests: Bool {
|
||||
#if DEBUG
|
||||
processInfo.environment["IS_RUNNING_INTEGRATION_TESTS"] == "1"
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Flag indicating whether the app is running the UI tests or unit tests.
|
||||
static var isRunningTests: Bool {
|
||||
isRunningUITests || isRunningUnitTests
|
||||
isRunningUITests || isRunningUnitTests || isRunningIntegrationTests
|
||||
}
|
||||
|
||||
/// The identifier of the screen to be loaded when running UI tests.
|
||||
|
@ -33,6 +33,8 @@ struct FullscreenDialog<Content: View, BottomContent: View>: View {
|
||||
/// The spacing between the content and the buttons.
|
||||
var spacing: CGFloat = 16
|
||||
|
||||
var showBackgroundGradient = false
|
||||
|
||||
/// The main content shown at the top of the layout.
|
||||
@ViewBuilder var content: () -> Content
|
||||
/// The content shown at the bottom of the layout.
|
||||
@ -62,6 +64,18 @@ struct FullscreenDialog<Content: View, BottomContent: View>: View {
|
||||
}
|
||||
.scrollBounceBehavior(.basedOnSize)
|
||||
.safeAreaInset(edge: .bottom) {
|
||||
if showBackgroundGradient {
|
||||
adjustedBottomContent(geometry: geometry)
|
||||
.background(Asset.Images.backgroundBottom.swiftUIImage.resizable().ignoresSafeArea())
|
||||
} else {
|
||||
adjustedBottomContent(geometry: geometry)
|
||||
.background()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func adjustedBottomContent(geometry: GeometryProxy) -> some View {
|
||||
VStack(spacing: 0) {
|
||||
bottomContent()
|
||||
.readableFrame()
|
||||
@ -72,13 +86,10 @@ struct FullscreenDialog<Content: View, BottomContent: View>: View {
|
||||
Spacer()
|
||||
.frame(height: UIConstants.spacerHeight(in: geometry))
|
||||
}
|
||||
.background()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A continuously scrolling layout used for accessibility font sizes.
|
||||
var accessibilityLayout: some View {
|
||||
private var accessibilityLayout: some View {
|
||||
GeometryReader { geometry in
|
||||
ScrollView {
|
||||
VStack(spacing: 0) {
|
||||
|
@ -21,35 +21,61 @@ import SwiftUI
|
||||
/// takes a compound icon. If you would like to apply it to an SFSymbol, you can call
|
||||
/// the `heroImage()` modifier directly on the Image.
|
||||
struct HeroImage: View {
|
||||
enum Style {
|
||||
case normal
|
||||
case positive
|
||||
|
||||
var foregroundColor: Color {
|
||||
switch self {
|
||||
case .normal:
|
||||
return .compound.iconPrimary
|
||||
case .positive:
|
||||
return .compound.iconSuccessPrimary
|
||||
}
|
||||
}
|
||||
|
||||
var backgroundFillColor: Color {
|
||||
switch self {
|
||||
case .normal:
|
||||
return .compound.bgSubtleSecondary
|
||||
case .positive:
|
||||
return .compound.bgSuccessSubtle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The icon that is shown.
|
||||
let icon: KeyPath<CompoundIcons, Image>
|
||||
var style: Style = .normal
|
||||
|
||||
var body: some View {
|
||||
CompoundIcon(icon, size: .custom(42), relativeTo: .title)
|
||||
.modifier(HeroImageModifier())
|
||||
.modifier(HeroImageModifier(style: style))
|
||||
}
|
||||
}
|
||||
|
||||
extension Image {
|
||||
/// Styles the image for use as the main/top/hero screen icon. You should prefer
|
||||
/// the HeroImage component when possible, by using an icon from Compound.
|
||||
func heroImage(insets: CGFloat = 16) -> some View {
|
||||
func heroImage(insets: CGFloat = 16, style: HeroImage.Style = .normal) -> some View {
|
||||
resizable()
|
||||
.renderingMode(.template)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.scaledPadding(insets, relativeTo: .title)
|
||||
.modifier(HeroImageModifier())
|
||||
.modifier(HeroImageModifier(style: style))
|
||||
}
|
||||
}
|
||||
|
||||
private struct HeroImageModifier: ViewModifier {
|
||||
let style: HeroImage.Style
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.foregroundColor(.compound.iconPrimary)
|
||||
.scaledFrame(size: 70, relativeTo: .title)
|
||||
.foregroundColor(style.foregroundColor)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 14)
|
||||
.fill(Color.compound.bgSubtleSecondary)
|
||||
.fill(style.backgroundFillColor)
|
||||
}
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private static let loadingIndicatorIdentifier = "LoginCoordinatorLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(LoginScreenCoordinatorAction.self)-Loading"
|
||||
|
||||
private func startLoading(isInteractionBlocking: Bool) {
|
||||
if isInteractionBlocking {
|
||||
|
@ -104,7 +104,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private static let loadingIndicatorIdentifier = "SoftLogoutLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(SoftLogoutScreenCoordinator.self)-Loading"
|
||||
|
||||
/// Show an activity indicator whilst loading.
|
||||
@MainActor private func startLoading() {
|
||||
|
@ -82,7 +82,7 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers
|
||||
|
||||
// MARK: Loading indicator
|
||||
|
||||
private static let loadingIndicatorIdentifier = "BlockedUsersLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(BlockedUsersScreenViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -90,7 +90,7 @@ final class BugReportScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private static let loadingIndicatorIdentifier = "BugReportLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(BugReportScreenCoordinator.self)-Loading"
|
||||
|
||||
private func startLoading(label: String = L10n.commonLoading, progressPublisher: CurrentValuePublisher<Double, Never>) {
|
||||
parameters.userIndicatorController?.submitIndicator(
|
||||
|
@ -171,7 +171,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol
|
||||
|
||||
// MARK: Loading indicator
|
||||
|
||||
private static let loadingIndicatorIdentifier = "CreateRoomLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(CreateRoomViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -31,7 +31,6 @@ enum HomeScreenCoordinatorAction {
|
||||
case roomLeft(roomIdentifier: String)
|
||||
case presentSettingsScreen
|
||||
case presentFeedbackScreen
|
||||
case presentSessionVerificationScreen
|
||||
case presentSecureBackupSettings
|
||||
case presentStartChatScreen
|
||||
case presentInvitesScreen
|
||||
@ -74,8 +73,6 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentFeedbackScreen)
|
||||
case .presentSettingsScreen:
|
||||
actionsSubject.send(.presentSettingsScreen)
|
||||
case .presentSessionVerificationScreen:
|
||||
actionsSubject.send(.presentSessionVerificationScreen)
|
||||
case .presentSecureBackupSettings:
|
||||
actionsSubject.send(.presentSecureBackupSettings)
|
||||
case .logout:
|
||||
|
@ -22,7 +22,6 @@ enum HomeScreenViewModelAction {
|
||||
case presentRoom(roomIdentifier: String)
|
||||
case presentRoomDetails(roomIdentifier: String)
|
||||
case roomLeft(roomIdentifier: String)
|
||||
case presentSessionVerificationScreen
|
||||
case presentSecureBackupSettings
|
||||
case presentSettingsScreen
|
||||
case presentFeedbackScreen
|
||||
@ -39,9 +38,7 @@ enum HomeScreenViewAction {
|
||||
case confirmLeaveRoom(roomIdentifier: String)
|
||||
case showSettings
|
||||
case startChat
|
||||
case verifySession
|
||||
case confirmRecoveryKey
|
||||
case skipSessionVerification
|
||||
case skipRecoveryKeyConfirmation
|
||||
case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
|
||||
case selectInvites
|
||||
@ -74,7 +71,6 @@ enum HomeScreenRoomListMode: CustomStringConvertible {
|
||||
enum SecurityBannerMode {
|
||||
case none
|
||||
case dismissed
|
||||
case sessionVerification
|
||||
case recoveryKeyConfirmation
|
||||
}
|
||||
|
||||
|
@ -70,11 +70,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
guard let self else { return }
|
||||
|
||||
switch (securityState.verificationState, securityState.recoveryState) {
|
||||
case (.unverified, _):
|
||||
state.requiresExtraAccountSetup = true
|
||||
if state.securityBannerMode != .dismissed {
|
||||
state.securityBannerMode = .sessionVerification
|
||||
}
|
||||
case (.verified, .disabled):
|
||||
state.requiresExtraAccountSetup = true
|
||||
state.securityBannerMode = .none
|
||||
@ -134,12 +129,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
leaveRoom(roomId: roomIdentifier)
|
||||
case .showSettings:
|
||||
actionsSubject.send(.presentSettingsScreen)
|
||||
case .verifySession:
|
||||
actionsSubject.send(.presentSessionVerificationScreen)
|
||||
case .confirmRecoveryKey:
|
||||
actionsSubject.send(.presentSecureBackupSettings)
|
||||
case .skipSessionVerification:
|
||||
state.securityBannerMode = .dismissed
|
||||
case .skipRecoveryKeyConfirmation:
|
||||
state.securityBannerMode = .dismissed
|
||||
case .updateVisibleItemRange(let range, let isScrolling):
|
||||
|
@ -103,16 +103,13 @@ struct HomeScreenContent: View {
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
/// The session verification banner and invites button if either are needed.
|
||||
private var topSection: some View {
|
||||
VStack(spacing: 0) {
|
||||
if !context.isSearchFieldFocused {
|
||||
RoomListFiltersView(state: $context.filtersState)
|
||||
}
|
||||
|
||||
if context.viewState.securityBannerMode == .sessionVerification {
|
||||
HomeScreenSessionVerificationBanner(context: context)
|
||||
} else if context.viewState.securityBannerMode == .recoveryKeyConfirmation {
|
||||
if context.viewState.securityBannerMode == .recoveryKeyConfirmation {
|
||||
HomeScreenRecoveryKeyConfirmationBanner(context: context)
|
||||
}
|
||||
|
||||
|
@ -1,81 +0,0 @@
|
||||
//
|
||||
// Copyright 2023 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
|
||||
|
||||
struct HomeScreenSessionVerificationBanner: View {
|
||||
@ObservedObject var context: HomeScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack(spacing: 16) {
|
||||
Text(L10n.sessionVerificationBannerTitle)
|
||||
.font(.compound.bodyLGSemibold)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
context.send(viewAction: .skipSessionVerification)
|
||||
} label: {
|
||||
Image(systemName: "xmark")
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.frame(width: 12, height: 12)
|
||||
}
|
||||
}
|
||||
Text(L10n.sessionVerificationBannerMessage)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
}
|
||||
|
||||
Button(L10n.actionContinue) {
|
||||
context.send(viewAction: .verifySession)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.buttonStyle(.compound(.primary, size: .medium))
|
||||
.accessibilityIdentifier(A11yIdentifiers.homeScreen.verificationBannerContinue)
|
||||
}
|
||||
.padding(16)
|
||||
.background(Color.compound.bgSubtleSecondary)
|
||||
.cornerRadius(14)
|
||||
.padding(.horizontal, 16)
|
||||
}
|
||||
}
|
||||
|
||||
struct HomeScreenSessionVerificationBanner_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = buildViewModel()
|
||||
|
||||
static var previews: some View {
|
||||
HomeScreenSessionVerificationBanner(context: viewModel.context)
|
||||
}
|
||||
|
||||
static func buildViewModel() -> HomeScreenViewModel {
|
||||
let clientProxy = ClientProxyMock(.init(userID: "@alice:example.com",
|
||||
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loading))))
|
||||
|
||||
let userSession = MockUserSession(clientProxy: clientProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
}
|
@ -63,7 +63,7 @@ struct CameraPicker: UIViewControllerRepresentable {
|
||||
self.cameraPicker = cameraPicker
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "CameraPickerLoadingIndicator"
|
||||
private static let loadingIndicatorIdentifier = "\(CameraPicker.self)-Loading"
|
||||
|
||||
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
|
||||
picker.delegate = nil
|
||||
|
@ -62,7 +62,7 @@ struct DocumentPicker: UIViewControllerRepresentable {
|
||||
documentPicker.callback(.cancel)
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "DocumentPickerLoadingIndicator"
|
||||
private static let loadingIndicatorIdentifier = "\(DocumentPicker.self)-Loading"
|
||||
|
||||
func documentPicker(_ picker: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
guard let url = urls.first else {
|
||||
|
@ -62,7 +62,7 @@ struct PhotoLibraryPicker: UIViewControllerRepresentable {
|
||||
|
||||
// MARK: PHPickerViewControllerDelegate
|
||||
|
||||
private static let loadingIndicatorIdentifier = "PhotoLibraryPickerLoadingIndicator"
|
||||
private static let loadingIndicatorIdentifier = "\(PhotoLibraryPicker.self)-Loading"
|
||||
|
||||
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
||||
guard let provider = results.first?.itemProvider,
|
||||
|
@ -102,7 +102,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
||||
}
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "MediaUploadPreviewLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(MediaUploadPreviewScreenViewModel.self)-Loading"
|
||||
|
||||
private func startLoading(progressPublisher: CurrentValuePublisher<Double, Never>) {
|
||||
userIndicatorController.submitIndicator(
|
||||
|
@ -21,7 +21,7 @@ struct AnalyticsPromptScreen: View {
|
||||
@ObservedObject var context: AnalyticsPromptScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding) {
|
||||
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding, showBackgroundGradient: true) {
|
||||
mainContent
|
||||
} bottomContent: {
|
||||
buttons
|
||||
@ -30,6 +30,7 @@ struct AnalyticsPromptScreen: View {
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
|
||||
/// The main content of the screen that is shown inside the scroll view.
|
||||
@ -88,10 +89,7 @@ struct AnalyticsPromptScreen: View {
|
||||
/// The stack of enable/disable buttons.
|
||||
private var buttons: some View {
|
||||
VStack(spacing: 16) {
|
||||
Button { context.send(viewAction: .enable) } label: {
|
||||
Text(L10n.actionOk)
|
||||
.font(.compound.bodyLGSemibold)
|
||||
}
|
||||
Button(L10n.actionOk) { context.send(viewAction: .enable) }
|
||||
.buttonStyle(.compound(.primary))
|
||||
.accessibilityIdentifier(A11yIdentifiers.analyticsPromptScreen.enable)
|
||||
|
@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// periphery:ignore:all - this is just a identityConfirmation remove this comment once generating the final file
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct IdentityConfirmationScreenCoordinatorParameters {
|
||||
let userSession: UserSessionProtocol
|
||||
let appSettings: AppSettings
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
}
|
||||
|
||||
enum IdentityConfirmationScreenCoordinatorAction {
|
||||
case otherDevice
|
||||
case recoveryKey
|
||||
}
|
||||
|
||||
final class IdentityConfirmationScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: IdentityConfirmationScreenCoordinatorParameters
|
||||
private let viewModel: IdentityConfirmationScreenViewModelProtocol
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private let actionsSubject: PassthroughSubject<IdentityConfirmationScreenCoordinatorAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmationScreenCoordinatorAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(parameters: IdentityConfirmationScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = IdentityConfirmationScreenViewModel(userSession: parameters.userSession,
|
||||
appSettings: parameters.appSettings,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
}
|
||||
|
||||
func start() {
|
||||
viewModel.actionsPublisher.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
MXLog.info("Coordinator: received view model action: \(action)")
|
||||
switch action {
|
||||
case .otherDevice:
|
||||
actionsSubject.send(.otherDevice)
|
||||
case .recoveryKey:
|
||||
actionsSubject.send(.recoveryKey)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(IdentityConfirmationScreen(context: viewModel.context))
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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 IdentityConfirmationScreenViewModelAction {
|
||||
case otherDevice
|
||||
case recoveryKey
|
||||
}
|
||||
|
||||
struct IdentityConfirmationScreenViewState: BindableState {
|
||||
enum Mode {
|
||||
case recoveryOnly
|
||||
case recoveryAndVerification
|
||||
}
|
||||
|
||||
var mode = Mode.recoveryOnly
|
||||
let learnMoreURL: URL
|
||||
}
|
||||
|
||||
enum IdentityConfirmationScreenViewAction {
|
||||
case otherDevice
|
||||
case recoveryKey
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
//
|
||||
// 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 IdentityConfirmationScreenViewModelType = StateStoreViewModel<IdentityConfirmationScreenViewState, IdentityConfirmationScreenViewAction>
|
||||
|
||||
class IdentityConfirmationScreenViewModel: IdentityConfirmationScreenViewModelType, IdentityConfirmationScreenViewModelProtocol {
|
||||
private let userSession: UserSessionProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
private let actionsSubject: PassthroughSubject<IdentityConfirmationScreenViewModelAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmationScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(userSession: UserSessionProtocol, appSettings: AppSettings, userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.userSession = userSession
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
super.init(initialViewState: IdentityConfirmationScreenViewState(learnMoreURL: appSettings.encryptionURL))
|
||||
|
||||
userSession.sessionSecurityStatePublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] state in
|
||||
Task {
|
||||
await self?.updateWithSessionSecurityState(state)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
await updateWithSessionSecurityState(userSession.sessionSecurityStatePublisher.value)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: IdentityConfirmationScreenViewAction) {
|
||||
MXLog.info("View model: received view action: \(viewAction)")
|
||||
switch viewAction {
|
||||
case .otherDevice:
|
||||
actionsSubject.send(.otherDevice)
|
||||
case .recoveryKey:
|
||||
actionsSubject.send(.recoveryKey)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateWithSessionSecurityState(_ sessionSecurityState: SessionSecurityState) async {
|
||||
if sessionSecurityState.verificationState == .unknown {
|
||||
showLoadingIndicator()
|
||||
} else {
|
||||
hideLoadingIndicator()
|
||||
}
|
||||
|
||||
guard sessionSecurityState.verificationState == .unverified else {
|
||||
return
|
||||
}
|
||||
|
||||
guard case let .success(isOnlyDeviceLeft) = await userSession.clientProxy.isOnlyDeviceLeft() else {
|
||||
return
|
||||
}
|
||||
|
||||
state.mode = isOnlyDeviceLeft ? .recoveryOnly : .recoveryAndVerification
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "\(IdentityConfirmationScreenViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
type: .modal,
|
||||
title: L10n.commonLoading,
|
||||
persistent: true))
|
||||
}
|
||||
|
||||
private func hideLoadingIndicator() {
|
||||
userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 IdentityConfirmationScreenViewModelProtocol {
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmationScreenViewModelAction, Never> { get }
|
||||
var context: IdentityConfirmationScreenViewModelType.Context { get }
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct IdentityConfirmationScreen: View {
|
||||
@ObservedObject var context: IdentityConfirmationScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding) {
|
||||
screenHeader
|
||||
} bottomContent: {
|
||||
actionButtons
|
||||
}
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@ViewBuilder
|
||||
private var screenHeader: some View {
|
||||
VStack(spacing: 0) {
|
||||
HeroImage(icon: \.lockSolid)
|
||||
.padding(.bottom, 16)
|
||||
|
||||
Text(L10n.screenIdentityConfirmationTitle)
|
||||
.font(.compound.headingMDBold)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Text(L10n.screenIdentityConfirmationSubtitle)
|
||||
.font(.compound.bodyMD)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
|
||||
Button(L10n.actionLearnMore) {
|
||||
UIApplication.shared.open(context.viewState.learnMoreURL)
|
||||
}
|
||||
.buttonStyle(.compound(.plain))
|
||||
.padding(.top, 16)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var actionButtons: some View {
|
||||
VStack(spacing: 32) {
|
||||
switch context.viewState.mode {
|
||||
case .recoveryOnly:
|
||||
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
|
||||
context.send(viewAction: .recoveryKey)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
|
||||
case .recoveryAndVerification:
|
||||
Button(L10n.actionStartVerification) {
|
||||
context.send(viewAction: .otherDevice)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
|
||||
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
|
||||
context.send(viewAction: .recoveryKey)
|
||||
}
|
||||
.buttonStyle(.compound(.plain))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct IdentityConfirmationScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
IdentityConfirmationScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
||||
|
||||
private static var viewModel: IdentityConfirmationScreenViewModel {
|
||||
let userSession = MockUserSession(clientProxy: ClientProxyMock(.init(userID: "@user:example.com",
|
||||
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))))),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
return IdentityConfirmationScreenViewModel(userSession: userSession,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// periphery:ignore:all - this is just a identityConfirmed remove this comment once generating the final file
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct IdentityConfirmedScreenCoordinatorParameters { }
|
||||
|
||||
enum IdentityConfirmedScreenCoordinatorAction {
|
||||
case done
|
||||
}
|
||||
|
||||
final class IdentityConfirmedScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: IdentityConfirmedScreenCoordinatorParameters
|
||||
private let viewModel: IdentityConfirmedScreenViewModelProtocol
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private let actionsSubject: PassthroughSubject<IdentityConfirmedScreenCoordinatorAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmedScreenCoordinatorAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(parameters: IdentityConfirmedScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = IdentityConfirmedScreenViewModel()
|
||||
}
|
||||
|
||||
func start() {
|
||||
viewModel.actionsPublisher.sink { [weak self] action in
|
||||
MXLog.info("Coordinator: received view model action: \(action)")
|
||||
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .done:
|
||||
self.actionsSubject.send(.done)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(IdentityConfirmedScreen(context: viewModel.context))
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
// 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.
|
||||
@ -16,7 +16,12 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct EncryptedHistoryRoomTimelineItem: DecorationTimelineItemProtocol, Equatable {
|
||||
let id: TimelineItemIdentifier
|
||||
let isSessionVerified: Bool
|
||||
enum IdentityConfirmedScreenViewModelAction {
|
||||
case done
|
||||
}
|
||||
|
||||
struct IdentityConfirmedScreenViewState: BindableState { }
|
||||
|
||||
enum IdentityConfirmedScreenViewAction {
|
||||
case done
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
typealias IdentityConfirmedScreenViewModelType = StateStoreViewModel<IdentityConfirmedScreenViewState, IdentityConfirmedScreenViewAction>
|
||||
|
||||
class IdentityConfirmedScreenViewModel: IdentityConfirmedScreenViewModelType, IdentityConfirmedScreenViewModelProtocol {
|
||||
private let actionsSubject: PassthroughSubject<IdentityConfirmedScreenViewModelAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmedScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init(initialViewState: .init())
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: IdentityConfirmedScreenViewAction) {
|
||||
MXLog.info("View model: received view action: \(viewAction)")
|
||||
|
||||
switch viewAction {
|
||||
case .done:
|
||||
actionsSubject.send(.done)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 IdentityConfirmedScreenViewModelProtocol {
|
||||
var actionsPublisher: AnyPublisher<IdentityConfirmedScreenViewModelAction, Never> { get }
|
||||
var context: IdentityConfirmedScreenViewModelType.Context { get }
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct IdentityConfirmedScreen: View {
|
||||
@ObservedObject var context: IdentityConfirmedScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding) {
|
||||
screenHeader
|
||||
} bottomContent: {
|
||||
actionButtons
|
||||
}
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@ViewBuilder
|
||||
private var screenHeader: some View {
|
||||
VStack(spacing: 0) {
|
||||
HeroImage(icon: \.checkCircle, style: .positive)
|
||||
.padding(.bottom, 16)
|
||||
|
||||
Text(L10n.screenIdentityConfirmedTitle)
|
||||
.font(.compound.headingMDBold)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Text(L10n.screenIdentityConfirmedSubtitle)
|
||||
.font(.compound.bodyMD)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var actionButtons: some View {
|
||||
Button(L10n.actionContinue) {
|
||||
context.send(viewAction: .done)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct IdentityConfirmedScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = IdentityConfirmedScreenViewModel()
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
IdentityConfirmedScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
struct NotificationPermissionsScreenCoordinatorParameters {
|
||||
let notificationManager: NotificationManagerProtocol
|
||||
}
|
||||
|
||||
enum NotificationPermissionsScreenCoordinatorAction {
|
||||
case done
|
||||
}
|
||||
|
||||
final class NotificationPermissionsScreenCoordinator: CoordinatorProtocol {
|
||||
private var viewModel: NotificationPermissionsScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<NotificationPermissionsScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
var actions: AnyPublisher<NotificationPermissionsScreenCoordinatorAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(parameters: NotificationPermissionsScreenCoordinatorParameters) {
|
||||
viewModel = NotificationPermissionsScreenViewModel(notificationManager: parameters.notificationManager)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func start() {
|
||||
viewModel.actionsPublisher
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .done:
|
||||
actionsSubject.send(.done)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(NotificationPermissionsScreen(context: viewModel.context))
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright 2021 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 NotificationPermissionsScreenViewAction {
|
||||
case enable
|
||||
case notNow
|
||||
}
|
||||
|
||||
enum NotificationPermissionsScreenViewModelAction {
|
||||
case done
|
||||
}
|
||||
|
||||
struct NotificationPermissionsScreenViewState: BindableState { }
|
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright 2021 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 NotificationPermissionsScreenViewModelType = StateStoreViewModel<NotificationPermissionsScreenViewState, NotificationPermissionsScreenViewAction>
|
||||
|
||||
class NotificationPermissionsScreenViewModel: NotificationPermissionsScreenViewModelType, NotificationPermissionsScreenViewModelProtocol {
|
||||
private let notificationManager: NotificationManagerProtocol
|
||||
|
||||
private var actionsSubject: PassthroughSubject<NotificationPermissionsScreenViewModelAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<NotificationPermissionsScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(notificationManager: NotificationManagerProtocol) {
|
||||
self.notificationManager = notificationManager
|
||||
|
||||
super.init(initialViewState: .init())
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: NotificationPermissionsScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .enable:
|
||||
notificationManager.requestAuthorization()
|
||||
|
||||
actionsSubject.send(.done)
|
||||
case .notNow:
|
||||
actionsSubject.send(.done)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Copyright 2021 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 NotificationPermissionsScreenViewModelProtocol {
|
||||
var actionsPublisher: AnyPublisher<NotificationPermissionsScreenViewModelAction, Never> { get }
|
||||
var context: NotificationPermissionsScreenViewModelType.Context { get }
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// A prompt that asks the user whether they would like to enable Analytics or not.
|
||||
struct NotificationPermissionsScreen: View {
|
||||
@ObservedObject var context: NotificationPermissionsScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: UIConstants.startScreenBreakerScreenTopPadding, showBackgroundGradient: true) {
|
||||
mainContent
|
||||
} bottomContent: {
|
||||
buttons
|
||||
}
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
|
||||
/// The main content of the screen that is shown inside the scroll view.
|
||||
private var mainContent: some View {
|
||||
VStack(spacing: 8) {
|
||||
HeroImage(icon: \.notificationsSolid)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Text(L10n.screenNotificationOptinTitle)
|
||||
.font(.compound.headingMDBold)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
|
||||
Text(L10n.screenNotificationOptinSubtitle)
|
||||
.font(.compound.bodyMD)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
|
||||
Asset.Images.notificationsPromptGraphic.swiftUIImage.resizable().aspectRatio(contentMode: .fit)
|
||||
}
|
||||
}
|
||||
|
||||
private var buttons: some View {
|
||||
VStack(spacing: 16) {
|
||||
Button(L10n.actionOk) { context.send(viewAction: .enable) }
|
||||
.buttonStyle(.compound(.primary))
|
||||
|
||||
Button { context.send(viewAction: .notNow) } label: {
|
||||
Text(L10n.actionNotNow)
|
||||
.font(.compound.bodyLGSemibold)
|
||||
.padding(14)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct NotificationPermissionsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = NotificationPermissionsScreenViewModel(notificationManager: NotificationManagerMock())
|
||||
static var previews: some View {
|
||||
NotificationPermissionsScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
@ -18,13 +18,11 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
enum SessionVerificationScreenCoordinatorAction {
|
||||
case recoveryKey
|
||||
case done
|
||||
}
|
||||
|
||||
struct SessionVerificationScreenCoordinatorParameters {
|
||||
let sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol
|
||||
let recoveryState: SecureBackupRecoveryState
|
||||
}
|
||||
|
||||
final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
|
||||
@ -38,8 +36,7 @@ final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: SessionVerificationScreenCoordinatorParameters) {
|
||||
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: parameters.sessionVerificationControllerProxy,
|
||||
recoveryState: parameters.recoveryState)
|
||||
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: parameters.sessionVerificationControllerProxy)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@ -50,8 +47,6 @@ final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .recoveryKey:
|
||||
actionsSubject.send(.recoveryKey)
|
||||
case .finished:
|
||||
actionsSubject.send(.done)
|
||||
}
|
||||
@ -59,6 +54,10 @@ final class SessionVerificationScreenCoordinator: CoordinatorProtocol {
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func stop() {
|
||||
viewModel.stop()
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(SessionVerificationScreen(context: viewModel.context))
|
||||
}
|
@ -17,13 +17,10 @@
|
||||
import Foundation
|
||||
|
||||
enum SessionVerificationScreenViewModelAction {
|
||||
case recoveryKey
|
||||
case finished
|
||||
}
|
||||
|
||||
struct SessionVerificationScreenViewState: BindableState {
|
||||
let showRecoveryOption: Bool
|
||||
|
||||
var verificationState: SessionVerificationScreenStateMachine.State = .initial
|
||||
|
||||
var title: String? {
|
||||
@ -86,11 +83,9 @@ struct SessionVerificationScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
enum SessionVerificationScreenViewAction {
|
||||
case recoveryKey
|
||||
case requestVerification
|
||||
case startSasVerification
|
||||
case restart
|
||||
case accept
|
||||
case decline
|
||||
case close
|
||||
}
|
@ -31,13 +31,12 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
|
||||
}
|
||||
|
||||
init(sessionVerificationControllerProxy: SessionVerificationControllerProxyProtocol,
|
||||
recoveryState: SecureBackupRecoveryState,
|
||||
verificationState: SessionVerificationScreenStateMachine.State = .initial) {
|
||||
self.sessionVerificationControllerProxy = sessionVerificationControllerProxy
|
||||
|
||||
stateMachine = SessionVerificationScreenStateMachine()
|
||||
|
||||
super.init(initialViewState: .init(showRecoveryOption: recoveryState == .incomplete, verificationState: verificationState))
|
||||
super.init(initialViewState: .init(verificationState: verificationState))
|
||||
|
||||
setupStateMachine()
|
||||
|
||||
@ -71,23 +70,12 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
|
||||
|
||||
override func process(viewAction: SessionVerificationScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .recoveryKey:
|
||||
actionsSubject.send(.recoveryKey)
|
||||
case .requestVerification:
|
||||
stateMachine.processEvent(.requestVerification)
|
||||
case .startSasVerification:
|
||||
stateMachine.processEvent(.startSasVerification)
|
||||
case .restart:
|
||||
stateMachine.processEvent(.restart)
|
||||
case .close:
|
||||
guard stateMachine.state == .initial ||
|
||||
stateMachine.state == .verified ||
|
||||
stateMachine.state == .cancelled else {
|
||||
stateMachine.processEvent(.cancel)
|
||||
return
|
||||
}
|
||||
|
||||
actionsSubject.send(.finished)
|
||||
case .accept:
|
||||
stateMachine.processEvent(.acceptChallenge)
|
||||
case .decline:
|
||||
@ -95,6 +83,14 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
let uncancellableStates: [SessionVerificationScreenStateMachine.State] = [.initial, .verified, .cancelled]
|
||||
|
||||
if !uncancellableStates.contains(stateMachine.state) {
|
||||
stateMachine.processEvent(.cancel)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupStateMachine() {
|
||||
@ -115,11 +111,7 @@ class SessionVerificationScreenViewModel: SessionVerificationViewModelType, Sess
|
||||
case (_, .cancel, .cancelling):
|
||||
cancelVerification()
|
||||
case (_, _, .verified):
|
||||
// Dismiss the success screen automatically.
|
||||
Task {
|
||||
try? await Task.sleep(for: .seconds(2))
|
||||
self.actionsSubject.send(.finished)
|
||||
}
|
||||
actionsSubject.send(.finished)
|
||||
default:
|
||||
break
|
||||
}
|
@ -20,4 +20,6 @@ import Combine
|
||||
protocol SessionVerificationScreenViewModelProtocol {
|
||||
var actions: AnyPublisher<SessionVerificationScreenViewModelAction, Never> { get }
|
||||
var context: SessionVerificationViewModelType.Context { get }
|
||||
|
||||
func stop()
|
||||
}
|
@ -20,23 +20,18 @@ struct SessionVerificationScreen: View {
|
||||
@ObservedObject var context: SessionVerificationScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollView {
|
||||
FullscreenDialog {
|
||||
VStack(spacing: 32) {
|
||||
screenHeader
|
||||
Spacer()
|
||||
mainContent
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.top, 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbarContent }
|
||||
} bottomContent: {
|
||||
actionButtons
|
||||
}
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.safeAreaInset(edge: .bottom) { actionButtons.padding() }
|
||||
}
|
||||
.interactiveDismissDisabled() // Make sure dismissal goes through the state machine(s).
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@ -44,7 +39,7 @@ struct SessionVerificationScreen: View {
|
||||
private var headerImageName: String {
|
||||
switch context.viewState.verificationState {
|
||||
case .initial:
|
||||
return "macbook.and.iphone"
|
||||
return "lock"
|
||||
case .cancelled:
|
||||
return "exclamationmark.shield"
|
||||
case .requestingVerification:
|
||||
@ -71,19 +66,24 @@ struct SessionVerificationScreen: View {
|
||||
@ViewBuilder
|
||||
private var screenHeader: some View {
|
||||
VStack(spacing: 0) {
|
||||
if context.viewState.verificationState == .initial {
|
||||
HeroImage(icon: \.lockSolid)
|
||||
.padding(.bottom, 16)
|
||||
} else {
|
||||
Image(systemName: headerImageName)
|
||||
.heroImage()
|
||||
.padding(.bottom, 16)
|
||||
}
|
||||
|
||||
Text(context.viewState.title ?? "")
|
||||
.font(.title2.bold())
|
||||
.font(.compound.headingMDBold)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.padding(.bottom, 8)
|
||||
.accessibilityIdentifier(context.viewState.titleAccessibilityIdentifier)
|
||||
|
||||
Text(context.viewState.message)
|
||||
.font(.subheadline)
|
||||
.font(.compound.bodyMD)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
}
|
||||
@ -134,14 +134,6 @@ struct SessionVerificationScreen: View {
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.requestVerification)
|
||||
|
||||
if context.viewState.showRecoveryOption {
|
||||
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
|
||||
context.send(viewAction: .recoveryKey)
|
||||
}
|
||||
.buttonStyle(.compound(.plain))
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.enterRecoveryKey)
|
||||
}
|
||||
}
|
||||
case .cancelled:
|
||||
Button(L10n.actionRetry) {
|
||||
@ -157,9 +149,9 @@ struct SessionVerificationScreen: View {
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.startSasVerification)
|
||||
|
||||
case .showingChallenge:
|
||||
VStack(spacing: 30) {
|
||||
Button { context.send(viewAction: .accept) } label: {
|
||||
Label(L10n.screenSessionVerificationTheyMatch, systemImage: "checkmark")
|
||||
VStack(spacing: 32) {
|
||||
Button(L10n.screenSessionVerificationTheyMatch) {
|
||||
context.send(viewAction: .accept)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.acceptChallenge)
|
||||
@ -172,12 +164,12 @@ struct SessionVerificationScreen: View {
|
||||
}
|
||||
|
||||
case .acceptingChallenge:
|
||||
VStack(spacing: 30) {
|
||||
VStack(spacing: 32) {
|
||||
Button { context.send(viewAction: .accept) } label: {
|
||||
HStack(spacing: 16) {
|
||||
ProgressView()
|
||||
.tint(.compound.textOnSolidPrimary)
|
||||
Label(L10n.screenSessionVerificationTheyMatch, systemImage: "checkmark")
|
||||
Text(L10n.screenSessionVerificationTheyMatch)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
@ -197,16 +189,6 @@ struct SessionVerificationScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder
|
||||
private var toolbarContent: some ToolbarContent {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .close)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.close)
|
||||
}
|
||||
}
|
||||
|
||||
struct EmojiView: View {
|
||||
let emoji: SessionVerificationEmoji
|
||||
|
||||
@ -244,7 +226,6 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static func sessionVerificationScreen(state: SessionVerificationScreenStateMachine.State) -> some View {
|
||||
let viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: SessionVerificationControllerProxyMock.configureMock(),
|
||||
recoveryState: .incomplete,
|
||||
verificationState: state)
|
||||
|
||||
return SessionVerificationScreen(context: viewModel.context)
|
@ -82,7 +82,7 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private static let loadingIndicatorIdentifier = "ReportContentLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(ReportContentScreenCoordinator.self)-Loading"
|
||||
|
||||
private func startLoading() {
|
||||
parameters.userIndicatorController.submitIndicator(
|
||||
|
@ -171,7 +171,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
|
||||
// MARK: Loading indicator
|
||||
|
||||
private static let loadingIndicatorIdentifier = "RoomMemberLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(RoomMemberDetailsScreenViewModel.self)-Loading"
|
||||
|
||||
private func showMemberLoadingIndicator() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -97,9 +97,8 @@ struct TimelineItemPlainStylerView<Content: View>: View {
|
||||
HStack(spacing: 8) {
|
||||
TimelineSenderAvatarView(timelineItem: timelineItem)
|
||||
Text(timelineItem.sender.displayName ?? timelineItem.sender.id)
|
||||
.font(.subheadline)
|
||||
.font(.compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.decorativeColor(for: timelineItem.sender.id).text)
|
||||
.fontWeight(.semibold)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.onTapGesture {
|
||||
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
/// The item shown when all previous items are un-decryptable due to
|
||||
/// key backup not yet being supported in the app.
|
||||
struct EncryptedHistoryRoomTimelineView: View {
|
||||
let timelineItem: EncryptedHistoryRoomTimelineItem
|
||||
|
||||
var body: some View {
|
||||
Label {
|
||||
Text(title)
|
||||
.font(.compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.textInfoPrimary)
|
||||
} icon: {
|
||||
CompoundIcon(\.infoSolid, size: .small, relativeTo: .compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.iconInfoPrimary)
|
||||
}
|
||||
.labelStyle(EncryptedHistoryLabelStyle())
|
||||
.padding(16)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.fill(Color.compound.bgInfoSubtle)
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.stroke(Color.compound.borderInfoSubtle)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 16)
|
||||
}
|
||||
|
||||
private var title: String {
|
||||
timelineItem.isSessionVerified ? L10n.screenRoomEncryptedHistoryBanner : L10n.screenRoomEncryptedHistoryBannerUnverified
|
||||
}
|
||||
}
|
||||
|
||||
private struct EncryptedHistoryLabelStyle: LabelStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .top, spacing: 16) {
|
||||
configuration.icon
|
||||
configuration.title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EncryptedHistoryRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
VStack(spacing: 8) {
|
||||
EncryptedHistoryRoomTimelineView(timelineItem: .init(id: .random, isSessionVerified: true))
|
||||
EncryptedHistoryRoomTimelineView(timelineItem: .init(id: .random, isSessionVerified: false))
|
||||
}
|
||||
}
|
||||
}
|
@ -86,7 +86,7 @@ class SecureBackupKeyBackupScreenViewModel: SecureBackupKeyBackupScreenViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "SecureBackupKeyBackupScreenLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(SecureBackupKeyBackupScreenViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
userIndicatorController?.submitIndicator(.init(id: Self.loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true))
|
||||
|
@ -22,11 +22,20 @@ struct SecureBackupKeyBackupScreen: View {
|
||||
@ObservedObject var context: SecureBackupKeyBackupScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog {
|
||||
mainContent
|
||||
.padding()
|
||||
} bottomContent: {
|
||||
Button(role: .destructive) {
|
||||
context.send(viewAction: .toggleBackup)
|
||||
} label: {
|
||||
Text(L10n.screenChatBackupKeyBackupActionDisable)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.interactiveDismissDisabled()
|
||||
.toolbar { toolbar }
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.alert(item: $context.alertInfo)
|
||||
}
|
||||
|
||||
@ -71,15 +80,6 @@ struct SecureBackupKeyBackupScreen: View {
|
||||
.foregroundColor(.compound.iconCriticalPrimary)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(role: .destructive) {
|
||||
context.send(viewAction: .toggleBackup)
|
||||
} label: {
|
||||
Text(L10n.screenChatBackupKeyBackupActionDisable)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,25 +22,20 @@ struct SecureBackupLogoutConfirmationScreen: View {
|
||||
@ObservedObject var context: SecureBackupLogoutConfirmationScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollView {
|
||||
FullscreenDialog {
|
||||
VStack(spacing: 16) {
|
||||
header
|
||||
HeroImage(icon: \.keyOffSolid)
|
||||
content
|
||||
}
|
||||
.padding()
|
||||
} bottomContent: {
|
||||
footer.padding()
|
||||
}
|
||||
.toolbar { toolbar }
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.safeAreaInset(edge: .bottom) { footer.padding() }
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.alert(item: $context.alertInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var header: some View {
|
||||
HeroImage(icon: \.keyOffSolid)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var content: some View {
|
||||
@ -62,6 +57,7 @@ struct SecureBackupLogoutConfirmationScreen: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var footer: some View {
|
||||
VStack(spacing: 16.0) {
|
||||
if context.viewState.mode == .saveRecoveryKey {
|
||||
Button {
|
||||
context.send(viewAction: .settings)
|
||||
@ -78,6 +74,7 @@ struct SecureBackupLogoutConfirmationScreen: View {
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder
|
||||
private var toolbar: some ToolbarContent {
|
||||
@ -88,7 +85,7 @@ struct SecureBackupLogoutConfirmationScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
private var title: String {
|
||||
switch context.viewState.mode {
|
||||
case .saveRecoveryKey:
|
||||
return L10n.screenSignoutSaveRecoveryKeyTitle
|
||||
@ -99,7 +96,7 @@ struct SecureBackupLogoutConfirmationScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
var subtitle: String {
|
||||
private var subtitle: String {
|
||||
switch context.viewState.mode {
|
||||
case .saveRecoveryKey:
|
||||
return L10n.screenSignoutSaveRecoveryKeySubtitle
|
||||
|
@ -20,6 +20,7 @@ import SwiftUI
|
||||
struct SecureBackupRecoveryKeyScreenCoordinatorParameters {
|
||||
let secureBackupController: SecureBackupControllerProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
let isModallyPresented: Bool
|
||||
}
|
||||
|
||||
enum SecureBackupRecoveryKeyScreenCoordinatorAction {
|
||||
@ -40,7 +41,8 @@ final class SecureBackupRecoveryKeyScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
init(parameters: SecureBackupRecoveryKeyScreenCoordinatorParameters) {
|
||||
viewModel = SecureBackupRecoveryKeyScreenViewModel(secureBackupController: parameters.secureBackupController,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
isModallyPresented: parameters.isModallyPresented)
|
||||
}
|
||||
|
||||
func start() {
|
||||
|
@ -28,6 +28,9 @@ enum SecureBackupRecoveryKeyScreenViewMode {
|
||||
}
|
||||
|
||||
struct SecureBackupRecoveryKeyScreenViewState: BindableState {
|
||||
/// Whether the screen is presented modally or within a navigation stack.
|
||||
var isModallyPresented: Bool
|
||||
|
||||
let mode: SecureBackupRecoveryKeyScreenViewMode
|
||||
|
||||
var recoveryKey: String?
|
||||
|
@ -28,11 +28,15 @@ class SecureBackupRecoveryKeyScreenViewModel: SecureBackupRecoveryKeyScreenViewM
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(secureBackupController: SecureBackupControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
init(secureBackupController: SecureBackupControllerProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
isModallyPresented: Bool) {
|
||||
self.secureBackupController = secureBackupController
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
super.init(initialViewState: .init(mode: secureBackupController.recoveryState.value.viewMode, bindings: .init()))
|
||||
super.init(initialViewState: .init(isModallyPresented: isModallyPresented,
|
||||
mode: secureBackupController.recoveryState.value.viewMode,
|
||||
bindings: .init()))
|
||||
|
||||
secureBackupController.recoveryState
|
||||
.receive(on: DispatchQueue.main)
|
||||
|
@ -24,7 +24,7 @@ struct SecureBackupRecoveryKeyScreen: View {
|
||||
private let textFieldIdentifier = "textFieldIdentifier"
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
FullscreenDialog {
|
||||
ScrollViewReader { reader in
|
||||
mainContent
|
||||
.padding(16)
|
||||
@ -33,17 +33,14 @@ struct SecureBackupRecoveryKeyScreen: View {
|
||||
reader.scrollTo(textFieldIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .bottom) {
|
||||
} bottomContent: {
|
||||
footer
|
||||
.padding([.horizontal, .bottom], 16)
|
||||
.padding(.top, 8)
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
.toolbar { toolbar }
|
||||
.toolbar(.visible, for: .navigationBar)
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
.background()
|
||||
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||
.interactiveDismissDisabled()
|
||||
.alert(item: $context.alertInfo)
|
||||
}
|
||||
|
||||
@ -101,7 +98,7 @@ struct SecureBackupRecoveryKeyScreen: View {
|
||||
|
||||
@ToolbarContentBuilder
|
||||
private var toolbar: some ToolbarContent {
|
||||
if context.viewState.recoveryKey == nil {
|
||||
if context.viewState.isModallyPresented == true, context.viewState.recoveryKey == nil {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .cancel)
|
||||
@ -235,6 +232,8 @@ struct SecureBackupRecoveryKeyScreen_Previews: PreviewProvider, TestablePreview
|
||||
let backupController = SecureBackupControllerMock()
|
||||
backupController.underlyingRecoveryState = CurrentValueSubject<SecureBackupRecoveryState, Never>(recoveryState).asCurrentValuePublisher()
|
||||
|
||||
return SecureBackupRecoveryKeyScreenViewModel(secureBackupController: backupController, userIndicatorController: UserIndicatorControllerMock())
|
||||
return SecureBackupRecoveryKeyScreenViewModel(secureBackupController: backupController,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
isModallyPresented: true)
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let recoveryKeyCoordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: .init(secureBackupController: parameters.secureBackupController,
|
||||
userIndicatorController: parameters.userIndicatorController))
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
isModallyPresented: true))
|
||||
|
||||
recoveryKeyCoordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
@ -33,7 +33,6 @@ enum SettingsScreenCoordinatorAction {
|
||||
case bugReport
|
||||
case about
|
||||
case blockedUsers
|
||||
case sessionVerification
|
||||
case accountSessions
|
||||
case notifications
|
||||
case advancedSettings
|
||||
@ -77,8 +76,6 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.about)
|
||||
case .blockedUsers:
|
||||
actionsSubject.send(.blockedUsers)
|
||||
case .sessionVerification:
|
||||
actionsSubject.send(.sessionVerification)
|
||||
case .secureBackup:
|
||||
actionsSubject.send(.secureBackup)
|
||||
case .accountSessionsList:
|
||||
|
@ -26,7 +26,6 @@ enum SettingsScreenViewModelAction {
|
||||
case reportBug
|
||||
case about
|
||||
case blockedUsers
|
||||
case sessionVerification
|
||||
case secureBackup
|
||||
case accountSessionsList
|
||||
case notifications
|
||||
@ -37,7 +36,6 @@ enum SettingsScreenViewModelAction {
|
||||
|
||||
enum SettingsScreenSecuritySectionMode {
|
||||
case none
|
||||
case sessionVerification
|
||||
case secureBackup
|
||||
}
|
||||
|
||||
@ -65,7 +63,6 @@ enum SettingsScreenViewAction {
|
||||
case reportBug
|
||||
case about
|
||||
case blockedUsers
|
||||
case sessionVerification
|
||||
case secureBackup
|
||||
case accountSessionsList
|
||||
case notifications
|
||||
|
@ -50,9 +50,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
guard let self else { return }
|
||||
|
||||
switch (securityState.verificationState, securityState.recoveryState) {
|
||||
case (.unverified, _):
|
||||
state.showSecuritySectionBadge = true
|
||||
state.securitySectionMode = .sessionVerification
|
||||
case (.verified, .disabled):
|
||||
state.showSecuritySectionBadge = true
|
||||
state.securitySectionMode = .secureBackup
|
||||
@ -107,8 +104,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
actionsSubject.send(.blockedUsers)
|
||||
case .logout:
|
||||
actionsSubject.send(.logout)
|
||||
case .sessionVerification:
|
||||
actionsSubject.send(.sessionVerification)
|
||||
case .secureBackup:
|
||||
actionsSubject.send(.secureBackup)
|
||||
case .notifications:
|
||||
|
@ -81,11 +81,6 @@ struct SettingsScreen: View {
|
||||
private var accountSecuritySection: some View {
|
||||
Section {
|
||||
switch context.viewState.securitySectionMode {
|
||||
case .sessionVerification:
|
||||
ListRow(label: .default(title: L10n.actionCompleteVerification,
|
||||
icon: \.checkCircle),
|
||||
details: context.viewState.showSecuritySectionBadge ? .icon(securitySectionBadge) : nil,
|
||||
kind: .button { context.send(viewAction: .sessionVerification) })
|
||||
case .secureBackup:
|
||||
ListRow(label: .default(title: L10n.commonChatBackup,
|
||||
icon: \.key),
|
||||
|
@ -190,7 +190,7 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
// MARK: Loading indicator
|
||||
|
||||
private static let loadingIndicatorIdentifier = "StartChatCoordinatorLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(StartChatScreenCoordinator.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -145,7 +145,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
|
||||
|
||||
// MARK: Loading indicator
|
||||
|
||||
private static let loadingIndicatorIdentifier = "StartChatLoading"
|
||||
private static let loadingIndicatorIdentifier = "\(StartChatScreenViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
|
@ -64,13 +64,6 @@ final class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
self?.enableNotifications(newValue)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
// Request authorization uppon UIApplication.didBecomeActiveNotification notification
|
||||
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
|
||||
.sink { [weak self] _ in
|
||||
self?.requestAuthorization()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func requestAuthorization() {
|
||||
|
@ -38,5 +38,6 @@ protocol NotificationManagerProtocol: AnyObject {
|
||||
func registrationFailed(with error: Error)
|
||||
func showLocalNotification(with title: String, subtitle: String?) async
|
||||
func setUserSession(_ userSession: UserSessionProtocol?)
|
||||
|
||||
func requestAuthorization()
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ import Foundation
|
||||
|
||||
struct MockRoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
|
||||
func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||
secureBackupController: SecureBackupControllerProtocol) -> RoomTimelineControllerProtocol {
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol {
|
||||
let timelineController = MockRoomTimelineController()
|
||||
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
|
||||
return timelineController
|
||||
|
@ -24,7 +24,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
private let timelineProvider: RoomTimelineProviderProtocol
|
||||
private let timelineItemFactory: RoomTimelineItemFactoryProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let secureBackupController: SecureBackupControllerProtocol
|
||||
private let serialDispatchQueue: DispatchQueue
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -39,13 +38,11 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||
appSettings: AppSettings,
|
||||
secureBackupController: SecureBackupControllerProtocol) {
|
||||
appSettings: AppSettings) {
|
||||
self.roomProxy = roomProxy
|
||||
timelineProvider = roomProxy.timeline.timelineProvider
|
||||
self.timelineItemFactory = timelineItemFactory
|
||||
self.appSettings = appSettings
|
||||
self.secureBackupController = secureBackupController
|
||||
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider", qos: .utility)
|
||||
|
||||
timelineProvider
|
||||
@ -253,7 +250,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = !roomProxy.timeline.timelineStartReached
|
||||
var isBackPaginating = false
|
||||
var lastEncryptedHistoryItemIndex: Int?
|
||||
|
||||
let collapsibleChunks = timelineProvider.itemProxies.groupBy { isItemCollapsible($0) }
|
||||
|
||||
@ -264,10 +260,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
let timelineItem = buildTimelineItem(for: itemProxy)
|
||||
|
||||
if timelineItem is EncryptedHistoryRoomTimelineItem {
|
||||
canBackPaginate = false
|
||||
}
|
||||
|
||||
return timelineItem
|
||||
}
|
||||
|
||||
@ -282,22 +274,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
continue
|
||||
}
|
||||
|
||||
if timelineItem is EncryptedHistoryRoomTimelineItem {
|
||||
lastEncryptedHistoryItemIndex = newTimelineItems.endIndex
|
||||
}
|
||||
|
||||
newTimelineItems.append(timelineItem)
|
||||
} else {
|
||||
newTimelineItems.append(CollapsibleTimelineItem(items: items))
|
||||
}
|
||||
}
|
||||
|
||||
if let lastEncryptedHistoryItemIndex {
|
||||
// Remove everything up to the last encrypted history item.
|
||||
// It only contains encrypted messages, state changes and date separators.
|
||||
newTimelineItems.removeFirst(lastEncryptedHistoryItemIndex)
|
||||
} else {
|
||||
// Otherwise check if we need to add anything to the top of the timeline.
|
||||
// Check if we need to add anything to the top of the timeline.
|
||||
switch timelineProvider.backPaginationState {
|
||||
case .timelineStartReached:
|
||||
if !roomProxy.isEncryptedOneToOneRoom {
|
||||
@ -311,7 +294,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
case .idle:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
timelineItems = newTimelineItems
|
||||
@ -327,16 +309,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
case .event(let eventTimelineItem):
|
||||
let timelineItem = timelineItemFactory.buildTimelineItem(for: eventTimelineItem, isDM: roomProxy.isEncryptedOneToOneRoom)
|
||||
|
||||
// When backup is enabled just show the timeline items, they will most likely
|
||||
// resolve eventually. If we don't know the backup state then we assume the session is not verified yet,
|
||||
// otherwise we just treat it as fully disabled.
|
||||
if secureBackupController.keyBackupState.value != .enabled {
|
||||
if timelineItem is EncryptedRoomTimelineItem, isItemInEncryptionHistory(eventTimelineItem) {
|
||||
return EncryptedHistoryRoomTimelineItem(id: eventTimelineItem.id,
|
||||
isSessionVerified: secureBackupController.keyBackupState.value != .unknown)
|
||||
}
|
||||
}
|
||||
|
||||
if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol {
|
||||
// Avoid fetching this over and over again as it changes states if it keeps failing to load
|
||||
// Errors will be handled again on appearance
|
||||
@ -359,13 +331,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not a specific item is part of the room's history that can't be decrypted due
|
||||
/// to the lack of key-backup. This is handled differently so we only show a single item.
|
||||
private func isItemInEncryptionHistory(_ itemProxy: EventTimelineItemProxy) -> Bool {
|
||||
guard roomProxy.isEncrypted, let lastLoginDate = appSettings.lastLoginDate else { return false }
|
||||
return itemProxy.timestamp < lastLoginDate
|
||||
}
|
||||
|
||||
private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool {
|
||||
if !appSettings.shouldCollapseRoomStateEvents {
|
||||
return false
|
||||
|
@ -18,11 +18,9 @@ import Foundation
|
||||
|
||||
struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
|
||||
func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||
secureBackupController: SecureBackupControllerProtocol) -> RoomTimelineControllerProtocol {
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol {
|
||||
RoomTimelineController(roomProxy: roomProxy,
|
||||
timelineItemFactory: timelineItemFactory,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
secureBackupController: secureBackupController)
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,5 @@ import Foundation
|
||||
@MainActor
|
||||
protocol RoomTimelineControllerFactoryProtocol {
|
||||
func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||
secureBackupController: SecureBackupControllerProtocol) -> RoomTimelineControllerProtocol
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol
|
||||
}
|
||||
|
@ -64,8 +64,6 @@ struct RoomTimelineItemView: View {
|
||||
UnsupportedRoomTimelineView(timelineItem: item)
|
||||
case .timelineStart(let item):
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
case .encryptedHistory(let item):
|
||||
EncryptedHistoryRoomTimelineView(timelineItem: item)
|
||||
case .state(let item):
|
||||
StateRoomTimelineView(timelineItem: item)
|
||||
case .group(let item):
|
||||
|
@ -60,7 +60,6 @@ enum RoomTimelineItemType: Equatable {
|
||||
case sticker(StickerRoomTimelineItem)
|
||||
case unsupported(UnsupportedRoomTimelineItem)
|
||||
case timelineStart(TimelineStartRoomTimelineItem)
|
||||
case encryptedHistory(EncryptedHistoryRoomTimelineItem)
|
||||
case state(StateRoomTimelineItem)
|
||||
case group(CollapsibleTimelineItem)
|
||||
case location(LocationRoomTimelineItem)
|
||||
@ -100,8 +99,6 @@ enum RoomTimelineItemType: Equatable {
|
||||
self = .unsupported(item)
|
||||
case let item as TimelineStartRoomTimelineItem:
|
||||
self = .timelineStart(item)
|
||||
case let item as EncryptedHistoryRoomTimelineItem:
|
||||
self = .encryptedHistory(item)
|
||||
case let item as StateRoomTimelineItem:
|
||||
self = .state(item)
|
||||
case let item as CollapsibleTimelineItem:
|
||||
@ -136,7 +133,6 @@ enum RoomTimelineItemType: Equatable {
|
||||
.sticker(let item as RoomTimelineItemProtocol),
|
||||
.unsupported(let item as RoomTimelineItemProtocol),
|
||||
.timelineStart(let item as RoomTimelineItemProtocol),
|
||||
.encryptedHistory(let item as RoomTimelineItemProtocol),
|
||||
.state(let item as RoomTimelineItemProtocol),
|
||||
.group(let item as RoomTimelineItemProtocol),
|
||||
.location(let item as RoomTimelineItemProtocol),
|
||||
|
@ -42,7 +42,7 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, WindowManagerDelegate {
|
||||
ServiceLocator.shared.register(userIndicatorController: UserIndicatorController())
|
||||
|
||||
AppSettings.configureWithSuiteName("io.element.elementx.uitests")
|
||||
AppSettings.reset()
|
||||
AppSettings.resetAllSettings()
|
||||
ServiceLocator.shared.register(appSettings: AppSettings())
|
||||
ServiceLocator.shared.register(bugReportService: BugReportServiceMock())
|
||||
ServiceLocator.shared.register(analytics: AnalyticsService(client: AnalyticsClientMock(),
|
||||
@ -149,7 +149,6 @@ class MockScreen: Identifiable {
|
||||
return navigationStackCoordinator
|
||||
case .authenticationFlow:
|
||||
let flowCoordinator = AuthenticationFlowCoordinator(authenticationService: MockAuthenticationServiceProxy(),
|
||||
appLockService: AppLockServiceMock(),
|
||||
bugReportService: BugReportServiceMock(),
|
||||
navigationRootCoordinator: navigationRootCoordinator,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
@ -567,8 +566,7 @@ class MockScreen: Identifiable {
|
||||
return navigationStackCoordinator
|
||||
case .sessionVerification:
|
||||
var sessionVerificationControllerProxy = SessionVerificationControllerProxyMock.configureMock(requestDelay: .seconds(5))
|
||||
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy,
|
||||
recoveryState: .unknown)
|
||||
let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy)
|
||||
return SessionVerificationScreenCoordinator(parameters: parameters)
|
||||
case .userSessionScreen, .userSessionScreenReply, .userSessionScreenRTE:
|
||||
let appSettings: AppSettings = ServiceLocator.shared.settings
|
||||
@ -586,7 +584,9 @@ class MockScreen: Identifiable {
|
||||
bugReportService: BugReportServiceMock(),
|
||||
roomTimelineControllerFactory: MockRoomTimelineControllerFactory(),
|
||||
appSettings: appSettings,
|
||||
analytics: ServiceLocator.shared.analytics)
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
notificationManager: NotificationManagerMock(),
|
||||
isNewLogin: false)
|
||||
|
||||
flowCoordinator.start()
|
||||
|
||||
|
@ -24,7 +24,7 @@ class UnitTestsAppCoordinator: AppCoordinatorProtocol {
|
||||
ServiceLocator.shared.register(userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
AppSettings.configureWithSuiteName("io.element.elementx.unittests")
|
||||
AppSettings.reset()
|
||||
AppSettings.resetAllSettings()
|
||||
ServiceLocator.shared.register(appSettings: AppSettings())
|
||||
ServiceLocator.shared.register(bugReportService: BugReportServiceMock())
|
||||
ServiceLocator.shared.register(analytics: AnalyticsService(client: AnalyticsClientMock(),
|
||||
|
@ -19,7 +19,14 @@ import XCTest
|
||||
enum Application {
|
||||
@discardableResult static func launch() -> XCUIApplication {
|
||||
let app = XCUIApplication()
|
||||
|
||||
var launchEnvironment = [
|
||||
"IS_RUNNING_INTEGRATION_TESTS": "1"
|
||||
]
|
||||
|
||||
app.launchEnvironment = launchEnvironment
|
||||
app.launch()
|
||||
|
||||
return app
|
||||
}
|
||||
}
|
||||
|
@ -66,32 +66,12 @@ extension XCUIApplication {
|
||||
currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: usernameTextField)
|
||||
currentTestCase.waitForExpectations(timeout: 300.0)
|
||||
|
||||
// Handle analytics prompt screen
|
||||
if staticTexts[A11yIdentifiers.analyticsPromptScreen.title].waitForExistence(timeout: 10.0) {
|
||||
// Wait for login and then handle save password sheet
|
||||
let savePasswordButton = buttons["Save Password"]
|
||||
if savePasswordButton.waitForExistence(timeout: 10.0) {
|
||||
savePasswordButton.tap()
|
||||
}
|
||||
|
||||
let enableButton = buttons[A11yIdentifiers.analyticsPromptScreen.enable]
|
||||
XCTAssertTrue(enableButton.waitForExistence(timeout: 10.0))
|
||||
enableButton.tap()
|
||||
}
|
||||
|
||||
// This might come in a different order, wait for both.
|
||||
let savePasswordButton = buttons["Save Password"]
|
||||
if savePasswordButton.waitForExistence(timeout: 10.0) {
|
||||
savePasswordButton.tap()
|
||||
}
|
||||
|
||||
// Handle the notifications permission alert https://stackoverflow.com/a/58171074/730924
|
||||
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
|
||||
let notificationAlertDeclineButton = springboard.buttons.element(boundBy: 0)
|
||||
if notificationAlertDeclineButton.waitForExistence(timeout: 10.0) {
|
||||
notificationAlertDeclineButton.tap()
|
||||
}
|
||||
|
||||
// Migration screen may be shown as an overlay.
|
||||
// if that pops up soon enough, we just let that happen and wait
|
||||
let message = staticTexts[A11yIdentifiers.migrationScreen.message]
|
||||
|
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-en-GB.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPad-pseudo.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-en-GB.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-en-GB.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-pseudo.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_analyticsPromptScreen-iPhone-15-pseudo.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPad-en-GB.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPad-en-GB.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPad-pseudo.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPad-pseudo.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPhone-15-en-GB.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPhone-15-en-GB.1.png
(Stored with Git LFS)
Binary file not shown.
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPhone-15-pseudo.1.png
(Stored with Git LFS)
BIN
PreviewTests/__Snapshots__/PreviewTests/test_homeScreenSessionVerificationBanner-iPhone-15-pseudo.1.png
(Stored with Git LFS)
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user