mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 13:37:11 +00:00
Add support for quick room search through the Cmd+K shortcut (#2363)
This commit is contained in:
parent
c442afa5f6
commit
197b088662
@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
@ -337,6 +337,7 @@
|
||||
5518DA4A6C9B4FC4B497EA9A /* LogViewerScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */; };
|
||||
558E2673B04FDD06A1A12DD3 /* LogViewerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */; };
|
||||
55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; };
|
||||
55D18AA4F4A2257642EBDB94 /* GlobalSearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */; };
|
||||
562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */; };
|
||||
564BF06B3E93D6DD55F903B2 /* CreateRoomCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */; };
|
||||
565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; };
|
||||
@ -486,6 +487,7 @@
|
||||
7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; };
|
||||
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; };
|
||||
7CFCC177F0ED083867FAD9C9 /* OnboardingScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E727F7E0BCE8A0BBFD33FF /* OnboardingScreenCoordinator.swift */; };
|
||||
7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */; };
|
||||
7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; };
|
||||
7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; };
|
||||
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; };
|
||||
@ -618,6 +620,7 @@
|
||||
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 */; };
|
||||
9F19096BFA629C0AC282B1E4 /* CreateRoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */; };
|
||||
9F30A18B50D13B10D8444984 /* ApplicationMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62011D547772F3DF5D924823 /* ApplicationMock.swift */; };
|
||||
9FAF6DA7E8E85C9699757764 /* CollapsibleRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */; };
|
||||
@ -674,6 +677,7 @@
|
||||
A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */; };
|
||||
A9D349478F7D4A2B1E40CEF9 /* LegalInformationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8977176AB534AA41630395BC /* LegalInformationScreenViewModelProtocol.swift */; };
|
||||
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 */; };
|
||||
AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; };
|
||||
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; };
|
||||
@ -832,10 +836,10 @@
|
||||
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 */; };
|
||||
D24A751C2E0E210CA6D551E4 /* OrientationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C68A1C3D46D8BDA743968E /* OrientationManager.swift */; };
|
||||
D2A15D03F81342A09340BD56 /* AnalyticsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFEEE93B82937B2E86F92EB /* AnalyticsScreen.swift */; };
|
||||
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
|
||||
D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */; };
|
||||
D34E328E9E65904358248FDD /* GlobalSearchScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */; };
|
||||
D3986615892E7CF05C86518A /* HomeScreenUserMenuButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BC2D3573D900A9C9F8C191 /* HomeScreenUserMenuButton.swift */; };
|
||||
D3FD96913D2B1AAA3149DAC7 /* CreateRoomViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */; };
|
||||
D415764645491F10344FC6AC /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F18AECC9D38C2B6D85F99C /* Publisher.swift */; };
|
||||
@ -886,6 +890,7 @@
|
||||
E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */; };
|
||||
E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */; };
|
||||
E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */; };
|
||||
E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */; };
|
||||
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */; };
|
||||
E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; };
|
||||
E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */; };
|
||||
@ -932,6 +937,7 @@
|
||||
EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */; };
|
||||
EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */; };
|
||||
EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F40F48279322E504153AB0D /* MockClientProxy.swift */; };
|
||||
EE56238683BC3ECA9BA00684 /* GlobalSearchScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */; };
|
||||
EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; };
|
||||
EE8A37E2A1A77DE5CF941632 /* StateRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */; };
|
||||
EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */; };
|
||||
@ -945,6 +951,7 @@
|
||||
F06CE9132855E81EBB6DDC32 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 940C605265DD82DA0C655E23 /* Kingfisher */; };
|
||||
F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */; };
|
||||
F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */; };
|
||||
F0DACC95F24128A54CD537E4 /* GlobalSearchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */; };
|
||||
F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; };
|
||||
F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */; };
|
||||
F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */; };
|
||||
@ -1066,7 +1073,7 @@
|
||||
033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||
035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = "<group>"; };
|
||||
0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = "<group>"; };
|
||||
0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
||||
0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
||||
03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = "<group>"; };
|
||||
@ -1126,7 +1133,7 @@
|
||||
127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = "<group>"; };
|
||||
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
|
||||
12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
||||
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
||||
130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = "<group>"; };
|
||||
13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
|
||||
@ -1191,6 +1198,7 @@
|
||||
225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilderProtocol.swift; sourceTree = "<group>"; };
|
||||
22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||
22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenCell.swift; sourceTree = "<group>"; };
|
||||
2355398E4A55DA5A89128AD1 /* EncryptionKeyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProvider.swift; sourceTree = "<group>"; };
|
||||
2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
23AA3F4B285570805CB0CCDD /* MapTiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTiler.swift; sourceTree = "<group>"; };
|
||||
@ -1198,6 +1206,7 @@
|
||||
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerTests.swift; sourceTree = "<group>"; };
|
||||
2441E2424E78A40FC95DBA76 /* AudioRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderTests.swift; sourceTree = "<group>"; };
|
||||
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = "<group>"; };
|
||||
24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreen.swift; sourceTree = "<group>"; };
|
||||
24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterView.swift; sourceTree = "<group>"; };
|
||||
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1265,6 +1274,7 @@
|
||||
37FEE10AB666891E6A675E5E /* SecureBackupLogoutConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreen.swift; sourceTree = "<group>"; };
|
||||
382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxyMock.swift; sourceTree = "<group>"; };
|
||||
38345442415E07A931197C55 /* AppLockScreenPINKeypad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenPINKeypad.swift; sourceTree = "<group>"; };
|
||||
38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreen.swift; sourceTree = "<group>"; };
|
||||
3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackgroundTaskService.swift; sourceTree = "<group>"; };
|
||||
398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = "<group>"; };
|
||||
@ -1306,6 +1316,7 @@
|
||||
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
||||
42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = "<group>"; };
|
||||
42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenModels.swift; sourceTree = "<group>"; };
|
||||
43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheProtocol.swift; sourceTree = "<group>"; };
|
||||
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareToMapsAppActivity.swift; sourceTree = "<group>"; };
|
||||
44C314C00533E2C297796B60 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
@ -1474,6 +1485,7 @@
|
||||
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>"; };
|
||||
7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
748AE77AC3B0A01223033B87 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
74C6F3DAD167F972702C8893 /* TimelineItemAccessibilityModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemAccessibilityModifier.swift; sourceTree = "<group>"; };
|
||||
@ -1558,7 +1570,7 @@
|
||||
8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = "<group>"; };
|
||||
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8E1BBA73B611EDEEA6E20E05 /* InvitesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenModels.swift; sourceTree = "<group>"; };
|
||||
8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = "<group>"; };
|
||||
@ -1684,7 +1696,6 @@
|
||||
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>"; };
|
||||
B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
B2C68A1C3D46D8BDA743968E /* OrientationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManager.swift; sourceTree = "<group>"; };
|
||||
B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenModels.swift; sourceTree = "<group>"; };
|
||||
B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationDialog.swift; sourceTree = "<group>"; };
|
||||
@ -1698,7 +1709,7 @@
|
||||
B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = "<group>"; };
|
||||
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
||||
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
||||
B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
B697816AF93DA06EC58C5D70 /* WaitlistScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1706,6 +1717,7 @@
|
||||
B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsCustomSectionView.swift; sourceTree = "<group>"; };
|
||||
B7884BD256C091EB511B2EDF /* AppLockSetupPINScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilder.swift; sourceTree = "<group>"; };
|
||||
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
||||
B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@ -1753,6 +1765,7 @@
|
||||
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>"; };
|
||||
C352359663A0E52BA20761EE /* LoadableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableImage.swift; sourceTree = "<group>"; };
|
||||
C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManagerProtocol.swift; sourceTree = "<group>"; };
|
||||
C49C1CEBA9BCF5D2AD1884FA /* OnboardingScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
C4CD503F5E0938FE53C7C6E7 /* UserDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@ -1802,7 +1815,7 @@
|
||||
CD95B3714F806AC9CF9A557B /* ComposerToolbarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModel.swift; sourceTree = "<group>"; };
|
||||
CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; };
|
||||
CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; };
|
||||
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
|
||||
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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>"; };
|
||||
@ -1899,6 +1912,7 @@
|
||||
E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = "<group>"; };
|
||||
E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = "<group>"; };
|
||||
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsNotificationCenter.swift; sourceTree = "<group>"; };
|
||||
@ -1908,7 +1922,7 @@
|
||||
ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.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>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = "<group>"; };
|
||||
ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = "<group>"; };
|
||||
EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
@ -1925,7 +1939,7 @@
|
||||
F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = "<group>"; };
|
||||
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
||||
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = "<group>"; };
|
||||
F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = "<group>"; };
|
||||
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = "<group>"; };
|
||||
F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
F36C0A6D59717193F49EA986 /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = "<group>"; };
|
||||
@ -2608,6 +2622,15 @@
|
||||
path = LegalInformationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
390C92506AD893EC593D405D /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */,
|
||||
22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
39557ADF21345E18F3865B9E /* Emojis */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3203,7 +3226,7 @@
|
||||
703929219780FFABAC6380AA /* Windowing */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B2C68A1C3D46D8BDA743968E /* OrientationManager.swift */,
|
||||
C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */,
|
||||
5A37E2FACFD041CE466223CD /* SceneDelegate.swift */,
|
||||
035177BCD8E8308B098AC3C2 /* WindowManager.swift */,
|
||||
06F27F588F9059128E17C669 /* WindowManagerProtocol.swift */,
|
||||
@ -3282,6 +3305,7 @@
|
||||
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */,
|
||||
84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */,
|
||||
1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */,
|
||||
EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */,
|
||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */,
|
||||
CC14E5209C262530E19BC4C1 /* InvitesScreenViewModelTests.swift */,
|
||||
845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */,
|
||||
@ -3638,6 +3662,18 @@
|
||||
path = MediaPickerScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */,
|
||||
436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */,
|
||||
38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */,
|
||||
B788615712FED326F73D3F83 /* GlobalSearchScreenViewModelProtocol.swift */,
|
||||
390C92506AD893EC593D405D /* View */,
|
||||
);
|
||||
path = GlobalSearchScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8A9C09B6A392465E03B8D1B1 /* IntegrationTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4500,6 +4536,7 @@
|
||||
C18958141C8ED6D778F779A4 /* CreateRoom */,
|
||||
F5A65D1D3B83593598DC278D /* EmojiPickerScreen */,
|
||||
448435400B561C40E514BE1C /* FilePreviewScreen */,
|
||||
8A4738BBA7C7A299BAD70372 /* GlobalSearchScreen */,
|
||||
B53CA9BECD3F97805E1432D0 /* HomeScreen */,
|
||||
E3EA13D6E41AD76151C2D100 /* InvitesScreen */,
|
||||
F12966DF3DA87FEF21348D60 /* InviteUsersScreen */,
|
||||
@ -5239,6 +5276,7 @@
|
||||
25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */,
|
||||
71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */,
|
||||
07756D532EFE33DD1FA258E5 /* GeoURITests.swift in Sources */,
|
||||
EE56238683BC3ECA9BA00684 /* GlobalSearchScreenViewModelTests.swift in Sources */,
|
||||
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */,
|
||||
A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */,
|
||||
A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */,
|
||||
@ -5518,6 +5556,12 @@
|
||||
F18CA61A58C77C84F551B8E7 /* GeneratedMocks.swift in Sources */,
|
||||
B53D292A5CA61E371C4CD785 /* GenericCallLinkCoordinator.swift in Sources */,
|
||||
4295E5F850897710A51AE114 /* GeoURI.swift in Sources */,
|
||||
F0DACC95F24128A54CD537E4 /* GlobalSearchScreen.swift in Sources */,
|
||||
9F11E743EA01482E78A438B0 /* GlobalSearchScreenCell.swift in Sources */,
|
||||
7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */,
|
||||
D34E328E9E65904358248FDD /* GlobalSearchScreenModels.swift in Sources */,
|
||||
55D18AA4F4A2257642EBDB94 /* GlobalSearchScreenViewModel.swift in Sources */,
|
||||
E32A18802EB37EEE3EF7B965 /* GlobalSearchScreenViewModelProtocol.swift in Sources */,
|
||||
D4D5595C4A2A702CFF4E94FF /* HeroImage.swift in Sources */,
|
||||
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */,
|
||||
62C5876C4254C58C2086F0DE /* HomeScreenContent.swift in Sources */,
|
||||
@ -5676,7 +5720,7 @@
|
||||
3A5BD701D1AC916AC534F52C /* OnboardingScreenModels.swift in Sources */,
|
||||
A5C5C18671EDD2747AC16D2D /* OnboardingScreenViewModel.swift in Sources */,
|
||||
4714991754A08B58B4D7ED85 /* OnboardingScreenViewModelProtocol.swift in Sources */,
|
||||
D24A751C2E0E210CA6D551E4 /* OrientationManager.swift in Sources */,
|
||||
AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */,
|
||||
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */,
|
||||
CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */,
|
||||
847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */,
|
||||
@ -6198,9 +6242,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_NSE",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_NSE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse";
|
||||
PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
|
||||
PRODUCT_NAME = NSE;
|
||||
@ -6231,9 +6273,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_MAIN_APP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP";
|
||||
PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(APP_NAME)";
|
||||
@ -6259,9 +6299,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_MAIN_APP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP";
|
||||
PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(APP_NAME)";
|
||||
@ -6504,9 +6542,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_NSE",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_NSE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse";
|
||||
PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
|
||||
PRODUCT_NAME = NSE;
|
||||
|
@ -263,7 +263,7 @@
|
||||
{
|
||||
"identity" : "swiftui-introspect",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/siteline/SwiftUI-Introspect",
|
||||
"location" : "https://github.com/siteline/SwiftUI-Introspect.git",
|
||||
"state" : {
|
||||
"revision" : "b94da693e57eaf79d16464b8b7c90d09cba4e290",
|
||||
"version" : "0.9.2"
|
||||
|
@ -4,8 +4,7 @@
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
runPostActionsOnFailure = "NO">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
@ -30,12 +29,6 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES"
|
||||
onlyGenerateCoverageForSpecifiedTargets = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
default = "YES"
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@ -45,10 +38,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<CodeCoverageTargets>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@ -58,6 +47,12 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</CodeCoverageTargets>
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -79,8 +74,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "HTTPS_PROXY"
|
||||
@ -115,8 +108,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
@ -24,10 +24,11 @@ class WindowManager: WindowManagerProtocol {
|
||||
|
||||
private(set) var mainWindow: UIWindow!
|
||||
private(set) var overlayWindow: UIWindow!
|
||||
private(set) var globalSearchWindow: UIWindow!
|
||||
private(set) var alternateWindow: UIWindow!
|
||||
|
||||
var windows: [UIWindow] {
|
||||
[mainWindow, overlayWindow, alternateWindow]
|
||||
[mainWindow, overlayWindow, globalSearchWindow, alternateWindow]
|
||||
}
|
||||
|
||||
// periphery:ignore - auto cancels when reassigned
|
||||
@ -50,6 +51,11 @@ class WindowManager: WindowManagerProtocol {
|
||||
overlayWindow.backgroundColor = .clear
|
||||
overlayWindow.isHidden = false
|
||||
|
||||
globalSearchWindow = UIWindow(windowScene: windowScene)
|
||||
globalSearchWindow.tintColor = .compound.textActionPrimary
|
||||
globalSearchWindow.backgroundColor = .clear
|
||||
globalSearchWindow.isHidden = true
|
||||
|
||||
alternateWindow = UIWindow(windowScene: windowScene)
|
||||
alternateWindow.tintColor = .compound.textActionPrimary
|
||||
|
||||
@ -60,6 +66,8 @@ class WindowManager: WindowManagerProtocol {
|
||||
mainWindow.isHidden = false
|
||||
overlayWindow.isHidden = false
|
||||
|
||||
mainWindow.makeKey()
|
||||
|
||||
switchTask = Task {
|
||||
// Delay hiding to make sure the main windows are visible.
|
||||
try await Task.sleep(for: windowHideDelay)
|
||||
@ -76,6 +84,8 @@ class WindowManager: WindowManagerProtocol {
|
||||
// e.g. the keyboard being displayed on top of a call sheet.
|
||||
mainWindow.endEditing(true)
|
||||
|
||||
hideGlobalSearch()
|
||||
|
||||
// alternateWindow.isHidden = false cannot got inside the Task otherwise the timing
|
||||
// is poor when you lock the phone - you briefly see the main window for a few
|
||||
// frames after you've unlocked the phone and then the placeholder animates in.
|
||||
@ -83,11 +93,30 @@ class WindowManager: WindowManagerProtocol {
|
||||
// Delay hiding to make sure the alternate window is visible.
|
||||
try await Task.sleep(for: windowHideDelay)
|
||||
|
||||
overlayWindow.isHidden = true
|
||||
mainWindow.isHidden = true
|
||||
overlayWindow.isHidden = true
|
||||
globalSearchWindow.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
func showGlobalSearch() {
|
||||
guard alternateWindow.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
globalSearchWindow.isHidden = false
|
||||
globalSearchWindow.makeKey()
|
||||
}
|
||||
|
||||
func hideGlobalSearch() {
|
||||
guard alternateWindow.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
globalSearchWindow.isHidden = true
|
||||
mainWindow.makeKey()
|
||||
}
|
||||
|
||||
func setOrientation(_ orientation: UIInterfaceOrientationMask) {
|
||||
windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
|
||||
}
|
||||
@ -103,7 +132,15 @@ private class PassthroughWindow: UIWindow {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let rootViewController else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard hitView != self else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the returned view is the `UIHostingController`'s view, ignore.
|
||||
return rootViewController?.view == hitView ? nil : hitView
|
||||
return rootViewController.view == hitView ? nil : hitView
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ protocol WindowManagerProtocol: AnyObject, OrientationManagerProtocol {
|
||||
var mainWindow: UIWindow! { get }
|
||||
/// Presented on top of the main window, to display e.g. user indicators.
|
||||
var overlayWindow: UIWindow! { get }
|
||||
/// A window layered on top of the main one. Used by the global search function
|
||||
var globalSearchWindow: UIWindow! { get }
|
||||
/// A secondary window that can be presented instead of the main/overlay window combo.
|
||||
var alternateWindow: UIWindow! { get }
|
||||
|
||||
@ -46,4 +48,9 @@ protocol WindowManagerProtocol: AnyObject, OrientationManagerProtocol {
|
||||
|
||||
/// Shows the alternate window, hiding the main and overlay combo.
|
||||
func switchToAlternate()
|
||||
|
||||
/// Makes the global search window key. Used to get automatic text field focus.
|
||||
func showGlobalSearch()
|
||||
|
||||
func hideGlobalSearch()
|
||||
}
|
||||
|
@ -978,7 +978,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
|
||||
private func presentMessageForwarding(for itemID: TimelineItemIdentifier) {
|
||||
guard let roomProxy, let roomSummaryProvider = userSession.clientProxy.messageForwardingRoomSummaryProvider, let eventID = itemID.eventID else {
|
||||
guard let roomProxy, let roomSummaryProvider = userSession.clientProxy.alternateRoomSummaryProvider, let eventID = itemID.eventID else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
@ -1002,7 +1002,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
await self.forward(eventID: eventID, toRoomID: roomID)
|
||||
}
|
||||
}
|
||||
}.store(in: &cancellables)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
stackCoordinator.setRootCoordinator(coordinator)
|
||||
|
||||
|
@ -25,9 +25,9 @@ enum UserSessionFlowCoordinatorAction {
|
||||
}
|
||||
|
||||
class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let windowManager: WindowManagerProtocol
|
||||
private let userSession: UserSessionProtocol
|
||||
private let navigationSplitCoordinator: NavigationSplitCoordinator
|
||||
private let windowManager: WindowManagerProtocol
|
||||
private let bugReportService: BugReportServiceProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let actionsSubject: PassthroughSubject<UserSessionFlowCoordinatorAction, Never> = .init()
|
||||
@ -41,6 +41,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
// periphery:ignore - retaining purpose
|
||||
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
|
||||
|
||||
// periphery:ignore - retaining purpose
|
||||
private var globalSearchScreenCoordinator: GlobalSearchScreenCoordinator?
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private let sidebarNavigationStackCoordinator: NavigationStackCoordinator
|
||||
@ -63,9 +66,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine = UserSessionFlowCoordinatorStateMachine()
|
||||
self.userSession = userSession
|
||||
self.navigationSplitCoordinator = navigationSplitCoordinator
|
||||
self.windowManager = windowManager
|
||||
self.bugReportService = bugReportService
|
||||
self.appSettings = appSettings
|
||||
self.windowManager = windowManager
|
||||
|
||||
sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
|
||||
detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
|
||||
@ -331,6 +334,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
Task { await self.runLogoutFlow() }
|
||||
case .presentInvitesScreen:
|
||||
stateMachine.processEvent(.showInvitesScreen)
|
||||
case .presentGlobalSearch:
|
||||
presentGlobalSearch()
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@ -528,4 +533,44 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
navigationSplitCoordinator.setSheetCoordinator(coordinator, animated: true)
|
||||
}
|
||||
|
||||
// MARK: Global search
|
||||
|
||||
private func presentGlobalSearch() {
|
||||
guard let roomSummaryProvider = userSession.clientProxy.alternateRoomSummaryProvider else {
|
||||
fatalError("Global search room summary provider unavailable")
|
||||
}
|
||||
|
||||
let coordinator = GlobalSearchScreenCoordinator(parameters: .init(roomSummaryProvider: roomSummaryProvider,
|
||||
mediaProvider: userSession.mediaProvider))
|
||||
|
||||
globalSearchScreenCoordinator = coordinator
|
||||
|
||||
coordinator.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .dismiss:
|
||||
dismissGlobalSearch()
|
||||
case .select(let roomID):
|
||||
dismissGlobalSearch()
|
||||
handleAppRoute(.room(roomID: roomID), animated: true)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
let hostingController = UIHostingController(rootView: coordinator.toPresentable())
|
||||
hostingController.view.backgroundColor = .clear
|
||||
windowManager.globalSearchWindow.rootViewController = hostingController
|
||||
|
||||
windowManager.showGlobalSearch()
|
||||
}
|
||||
|
||||
private func dismissGlobalSearch() {
|
||||
windowManager.globalSearchWindow.rootViewController = nil
|
||||
windowManager.hideGlobalSearch()
|
||||
|
||||
globalSearchScreenCoordinator = nil
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ enum RoomAvatarSizeOnScreen {
|
||||
case timeline
|
||||
case home
|
||||
case messageForwarding
|
||||
case globalSearch
|
||||
case details
|
||||
case notificationSettings
|
||||
|
||||
@ -97,6 +98,8 @@ enum RoomAvatarSizeOnScreen {
|
||||
return 32
|
||||
case .messageForwarding:
|
||||
return 36
|
||||
case .globalSearch:
|
||||
return 36
|
||||
case .home:
|
||||
return 52
|
||||
case .details:
|
||||
|
@ -0,0 +1,65 @@
|
||||
//
|
||||
// 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 Compound
|
||||
import SwiftUI
|
||||
|
||||
struct GlobalSearchScreenCoordinatorParameters {
|
||||
let roomSummaryProvider: RoomSummaryProviderProtocol
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
}
|
||||
|
||||
enum GlobalSearchControllerAction {
|
||||
case dismiss
|
||||
case select(roomID: String)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class GlobalSearchScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: GlobalSearchScreenCoordinatorParameters
|
||||
private let viewModel: GlobalSearchScreenViewModelProtocol
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private let actionsSubject: PassthroughSubject<GlobalSearchControllerAction, Never> = .init()
|
||||
var actions: AnyPublisher<GlobalSearchControllerAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(parameters: GlobalSearchScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider,
|
||||
imageProvider: parameters.mediaProvider)
|
||||
|
||||
viewModel.actions
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
case .select(let roomID):
|
||||
actionsSubject.send(.select(roomID: roomID))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(GlobalSearchScreen(context: viewModel.context))
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//
|
||||
// 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 GlobalSearchScreenViewModelAction {
|
||||
case dismiss
|
||||
case select(roomID: String)
|
||||
}
|
||||
|
||||
struct GlobalSearchScreenViewState: BindableState {
|
||||
var rooms = [GlobalSearchRoom]()
|
||||
var bindings: GlobalSearchScreenViewStateBindings
|
||||
}
|
||||
|
||||
struct GlobalSearchScreenViewStateBindings {
|
||||
var searchQuery: String
|
||||
}
|
||||
|
||||
enum GlobalSearchScreenViewAction {
|
||||
case dismiss
|
||||
case select(roomID: String)
|
||||
case reachedTop
|
||||
case reachedBottom
|
||||
}
|
||||
|
||||
struct GlobalSearchRoom: Identifiable, Equatable {
|
||||
let id: String
|
||||
let name: String
|
||||
let alias: String?
|
||||
let avatarURL: URL?
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
//
|
||||
// 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 GlobalSearchScreenViewModelType = StateStoreViewModel<GlobalSearchScreenViewState, GlobalSearchScreenViewAction>
|
||||
|
||||
class GlobalSearchScreenViewModel: GlobalSearchScreenViewModelType, GlobalSearchScreenViewModelProtocol {
|
||||
private let roomSummaryProvider: RoomSummaryProviderProtocol
|
||||
|
||||
private var actionsSubject: PassthroughSubject<GlobalSearchScreenViewModelAction, Never> = .init()
|
||||
var actions: AnyPublisher<GlobalSearchScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(roomSummaryProvider: RoomSummaryProviderProtocol,
|
||||
imageProvider: ImageProviderProtocol) {
|
||||
self.roomSummaryProvider = roomSummaryProvider
|
||||
|
||||
super.init(initialViewState: GlobalSearchScreenViewState(bindings: .init(searchQuery: "")),
|
||||
imageProvider: imageProvider)
|
||||
|
||||
roomSummaryProvider.roomListPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] summaries in
|
||||
self?.updateRooms(with: summaries)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
context.$viewState
|
||||
.map(\.bindings.searchQuery)
|
||||
.removeDuplicates()
|
||||
.sink { [weak self] searchQuery in
|
||||
self?.roomSummaryProvider.setFilter(.normalizedMatchRoomName(searchQuery))
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
updateRooms(with: roomSummaryProvider.roomListPublisher.value)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: GlobalSearchScreenViewAction) {
|
||||
MXLog.info("View model: received view action: \(viewAction)")
|
||||
|
||||
switch viewAction {
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
roomSummaryProvider.setFilter(.all) // This is a shared provider
|
||||
case .select(let roomID):
|
||||
actionsSubject.send(.select(roomID: roomID))
|
||||
case .reachedTop:
|
||||
updateVisibleRange(edge: .top)
|
||||
case .reachedBottom:
|
||||
updateVisibleRange(edge: .bottom)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateRooms(with summaries: [RoomSummary]) {
|
||||
state.rooms = summaries.compactMap { summary in
|
||||
switch summary {
|
||||
case .empty:
|
||||
return nil
|
||||
case .invalidated(let details), .filled(let details):
|
||||
return GlobalSearchRoom(id: details.id,
|
||||
name: details.name,
|
||||
alias: details.canonicalAlias,
|
||||
avatarURL: details.avatarURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual range values don't matter as long as they contain the lower
|
||||
/// or upper bounds. updateVisibleRange is a hybrid API that powers both
|
||||
/// sliding sync visible range update and list paginations
|
||||
/// For lists other than the home screen one we don't care about visible ranges,
|
||||
/// we just need the respective bounds to be there to trigger a next page load or
|
||||
/// a reset to just one page
|
||||
private func updateVisibleRange(edge: UIRectEdge) {
|
||||
switch edge {
|
||||
case .top:
|
||||
roomSummaryProvider.updateVisibleRange(0..<0)
|
||||
case .bottom:
|
||||
let roomCount = roomSummaryProvider.roomListPublisher.value.count
|
||||
roomSummaryProvider.updateVisibleRange(roomCount..<roomCount)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
@ -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 GlobalSearchScreenViewModelProtocol {
|
||||
var actions: AnyPublisher<GlobalSearchScreenViewModelAction, Never> { get }
|
||||
var context: GlobalSearchScreenViewModelType.Context { get }
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
//
|
||||
// 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 GlobalSearchScreen: View {
|
||||
@ObservedObject var context: GlobalSearchScreenViewModel.Context
|
||||
|
||||
@State private var selectedRoom: GlobalSearchRoom?
|
||||
@FocusState private var searchFieldFocus
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
header
|
||||
|
||||
Section {
|
||||
ForEach(context.viewState.rooms) { room in
|
||||
GlobalSearchScreenListRow(room: room, context: context)
|
||||
.listRowBackground(backgroundColor(for: room))
|
||||
.listRowInsets(.init())
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .select(roomID: room.id))
|
||||
}
|
||||
.onAppear {
|
||||
if room == context.viewState.rooms.first {
|
||||
context.send(viewAction: .reachedTop)
|
||||
} else if room == context.viewState.rooms.last {
|
||||
context.send(viewAction: .reachedBottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.plain)
|
||||
.frame(maxWidth: 700, maxHeight: 800)
|
||||
.background(.compound.bgCanvasDefault)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.black.opacity(0.5).ignoresSafeArea())
|
||||
.background { keyboardShortcuts }
|
||||
.onAppear {
|
||||
selectedRoom = context.viewState.rooms.first
|
||||
searchFieldFocus = true
|
||||
}
|
||||
.onChange(of: context.viewState.rooms) { _ in
|
||||
selectedRoom = context.viewState.rooms.first
|
||||
}
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .dismiss)
|
||||
}
|
||||
}
|
||||
|
||||
private var header: some View {
|
||||
GlobalSearchTextFieldRepresentable(placeholder: L10n.actionSearch, text: $context.searchQuery) { keyCode in
|
||||
switch keyCode {
|
||||
case .keyboardUpArrow:
|
||||
moveToNextEntry(backwards: true)
|
||||
return true
|
||||
case .keyboardDownArrow:
|
||||
moveToNextEntry()
|
||||
return true
|
||||
case .keyboardReturnOrEnter, .keyboardReturn:
|
||||
if let selectedRoom {
|
||||
context.send(viewAction: .select(roomID: selectedRoom.id))
|
||||
}
|
||||
return true
|
||||
case .keyboardEscape:
|
||||
context.send(viewAction: .dismiss)
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
} endEditingHandler: {
|
||||
if let selectedRoom {
|
||||
context.send(viewAction: .select(roomID: selectedRoom.id))
|
||||
} else { // Bring the focus back to the text field
|
||||
searchFieldFocus = true
|
||||
}
|
||||
}
|
||||
.focused($searchFieldFocus)
|
||||
.autocorrectionDisabled(true)
|
||||
.autocapitalization(.none)
|
||||
.textInputAutocapitalization(.never)
|
||||
}
|
||||
|
||||
private var keyboardShortcuts: some View {
|
||||
Group {
|
||||
Button("") {
|
||||
context.send(viewAction: .dismiss)
|
||||
}
|
||||
// Need this to enable escape on the textfield and forward the presses
|
||||
.keyboardShortcut(.escape, modifiers: [])
|
||||
}
|
||||
}
|
||||
|
||||
private func backgroundColor(for room: GlobalSearchRoom) -> Color {
|
||||
if selectedRoom == room {
|
||||
.compound.bgSubtlePrimary
|
||||
} else {
|
||||
.compound.bgCanvasDefault
|
||||
}
|
||||
}
|
||||
|
||||
private func moveToNextEntry(backwards: Bool = false) {
|
||||
guard let selectedRoom else {
|
||||
selectedRoom = context.viewState.rooms.first
|
||||
return
|
||||
}
|
||||
|
||||
guard let currentIndex = context.viewState.rooms.firstIndex(of: selectedRoom) else {
|
||||
return
|
||||
}
|
||||
|
||||
let nextIndex = (backwards ? currentIndex - 1 : currentIndex + 1)
|
||||
|
||||
guard context.viewState.rooms.indices.contains(nextIndex) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.selectedRoom = context.viewState.rooms[nextIndex]
|
||||
}
|
||||
}
|
||||
|
||||
private struct GlobalSearchTextFieldRepresentable: UIViewRepresentable {
|
||||
let placeholder: String
|
||||
@Binding var text: String
|
||||
let keyPressHandler: (UIKeyboardHIDUsage) -> Bool
|
||||
let endEditingHandler: () -> Void
|
||||
|
||||
func makeUIView(context: Context) -> UITextField {
|
||||
let textField = GlobalSearchTextField(keyPressHandler: keyPressHandler)
|
||||
textField.delegate = context.coordinator
|
||||
textField.autocorrectionType = .no
|
||||
textField.placeholder = placeholder
|
||||
return textField
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UITextField, context: Context) {
|
||||
uiView.text = text
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(text: $text, endEditingHandler: endEditingHandler)
|
||||
}
|
||||
|
||||
class Coordinator: NSObject, UITextFieldDelegate {
|
||||
var text: Binding<String>
|
||||
let endEditingHandler: () -> Void
|
||||
|
||||
init(text: Binding<String>, endEditingHandler: @escaping () -> Void) {
|
||||
self.text = text
|
||||
self.endEditingHandler = endEditingHandler
|
||||
}
|
||||
|
||||
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
// pressesBegan sometimes doesn't receive return events. Handle it here instead
|
||||
if string.rangeOfCharacter(from: .newlines) != nil {
|
||||
endEditingHandler()
|
||||
return false
|
||||
}
|
||||
|
||||
let currentText = textField.text ?? ""
|
||||
DispatchQueue.main.async {
|
||||
self.text.wrappedValue = (currentText as NSString).replacingCharacters(in: range, with: string)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class GlobalSearchTextField: UITextField {
|
||||
let keyPressHandler: (UIKeyboardHIDUsage) -> Bool
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
init(keyPressHandler: @escaping (UIKeyboardHIDUsage) -> Bool) {
|
||||
self.keyPressHandler = keyPressHandler
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
|
||||
guard let key = presses.first?.key else { return }
|
||||
|
||||
if keyPressHandler(key.keyCode) {
|
||||
return
|
||||
}
|
||||
|
||||
super.pressesBegan(presses, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct GlobalSearchScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: MockRoomSummaryProvider(state: .loaded(.mockRooms)),
|
||||
imageProvider: MockMediaProvider())
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
GlobalSearchScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
//
|
||||
// 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 Compound
|
||||
import SwiftUI
|
||||
|
||||
struct GlobalSearchScreenListRow: View {
|
||||
@Environment(\.dynamicTypeSize) var dynamicTypeSize
|
||||
|
||||
let room: GlobalSearchRoom
|
||||
let context: GlobalSearchScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
ZStack { // The list row swallows listRowBackgrounds for some reason
|
||||
ListRow(label: .avatar(title: room.name,
|
||||
description: room.alias ?? room.id,
|
||||
icon: avatar),
|
||||
kind: .label)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder @MainActor
|
||||
var avatar: some View {
|
||||
if dynamicTypeSize < .accessibility3 {
|
||||
LoadableAvatarImage(url: room.avatarURL,
|
||||
name: room.name,
|
||||
contentID: room.id,
|
||||
avatarSize: .room(on: .messageForwarding),
|
||||
imageProvider: context.imageProvider)
|
||||
.dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GlobalSearchScreenListRow_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: MockRoomSummaryProvider(state: .loaded(.mockRooms)),
|
||||
imageProvider: MockMediaProvider())
|
||||
|
||||
static var previews: some View {
|
||||
List {
|
||||
GlobalSearchScreenListRow(room: .init(id: "123",
|
||||
name: "Tech central",
|
||||
alias: "The best place in the whole wide world",
|
||||
avatarURL: .picturesDirectory),
|
||||
context: viewModel.context)
|
||||
}
|
||||
}
|
||||
}
|
@ -35,6 +35,7 @@ enum HomeScreenCoordinatorAction {
|
||||
case presentSecureBackupSettings
|
||||
case presentStartChatScreen
|
||||
case presentInvitesScreen
|
||||
case presentGlobalSearch
|
||||
case logout
|
||||
}
|
||||
|
||||
@ -82,6 +83,8 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentStartChatScreen)
|
||||
case .presentInvitesScreen:
|
||||
actionsSubject.send(.presentInvitesScreen)
|
||||
case .presentGlobalSearch:
|
||||
actionsSubject.send(.presentGlobalSearch)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
@ -28,6 +28,7 @@ enum HomeScreenViewModelAction {
|
||||
case presentFeedbackScreen
|
||||
case presentStartChatScreen
|
||||
case presentInvitesScreen
|
||||
case presentGlobalSearch
|
||||
case logout
|
||||
}
|
||||
|
||||
@ -49,6 +50,7 @@ enum HomeScreenViewAction {
|
||||
case skipRecoveryKeyConfirmation
|
||||
case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
|
||||
case selectInvites
|
||||
case globalSearch
|
||||
}
|
||||
|
||||
enum HomeScreenRoomListMode: CustomStringConvertible {
|
||||
|
@ -141,6 +141,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
actionsSubject.send(.presentStartChatScreen)
|
||||
case .selectInvites:
|
||||
actionsSubject.send(.presentInvitesScreen)
|
||||
case .globalSearch:
|
||||
actionsSubject.send(.presentGlobalSearch)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,12 @@ struct HomeScreenContent: View {
|
||||
.onChange(of: context.viewState.visibleRooms) { _ in
|
||||
updateVisibleRange()
|
||||
}
|
||||
.background(
|
||||
Button("", action: {
|
||||
context.send(viewAction: .globalSearch)
|
||||
})
|
||||
.keyboardShortcut(KeyEquivalent("k"), modifiers: [.command])
|
||||
)
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
.scrollDisabled(context.viewState.roomListMode == .skeletons)
|
||||
.scrollBounceBehavior(context.viewState.roomListMode == .empty ? .basedOnSize : .automatic)
|
||||
|
@ -60,6 +60,7 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me
|
||||
switch viewAction {
|
||||
case .cancel:
|
||||
actionsSubject.send(.dismiss)
|
||||
roomSummaryProvider?.setFilter(.all)
|
||||
case .send:
|
||||
guard let roomID = state.selectedRoomID else {
|
||||
fatalError()
|
||||
|
@ -54,7 +54,8 @@ final class RoomNotificationSettingsScreenCoordinator: CoordinatorProtocol {
|
||||
case .dismiss:
|
||||
self?.parameters.navigationStackCoordinator?.pop(animated: true)
|
||||
}
|
||||
}.store(in: &cancellables)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
|
@ -43,7 +43,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
// These following summary providers both operate on the same allRooms() list but
|
||||
// can apply their own filtering and pagination
|
||||
private(set) var roomSummaryProvider: RoomSummaryProviderProtocol?
|
||||
private(set) var messageForwardingRoomSummaryProvider: RoomSummaryProviderProtocol?
|
||||
private(set) var alternateRoomSummaryProvider: RoomSummaryProviderProtocol?
|
||||
|
||||
private(set) var inviteSummaryProvider: RoomSummaryProviderProtocol?
|
||||
|
||||
@ -505,6 +505,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
mentionBuilder: PlainMentionBuilder()))
|
||||
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID),
|
||||
messageEventStringBuilder: roomMessageEventStringBuilder)
|
||||
|
||||
roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
name: "AllRooms",
|
||||
@ -514,13 +515,13 @@ class ClientProxy: ClientProxyProtocol {
|
||||
appSettings: appSettings)
|
||||
try await roomSummaryProvider?.setRoomList(roomListService.allRooms())
|
||||
|
||||
messageForwardingRoomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
name: "MessageForwarding",
|
||||
notificationSettings: notificationSettings,
|
||||
backgroundTaskService: backgroundTaskService,
|
||||
appSettings: appSettings)
|
||||
try await messageForwardingRoomSummaryProvider?.setRoomList(roomListService.allRooms())
|
||||
alternateRoomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
name: "MessageForwarding",
|
||||
notificationSettings: notificationSettings,
|
||||
backgroundTaskService: backgroundTaskService,
|
||||
appSettings: appSettings)
|
||||
try await alternateRoomSummaryProvider?.setRoomList(roomListService.allRooms())
|
||||
|
||||
inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
|
@ -89,7 +89,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
||||
|
||||
var roomSummaryProvider: RoomSummaryProviderProtocol? { get }
|
||||
|
||||
var messageForwardingRoomSummaryProvider: RoomSummaryProviderProtocol? { get }
|
||||
/// Used for listing rooms that shouldn't be affected by the main `roomSummaryProvider` filtering
|
||||
var alternateRoomSummaryProvider: RoomSummaryProviderProtocol? { get }
|
||||
|
||||
var inviteSummaryProvider: RoomSummaryProviderProtocol? { get }
|
||||
|
||||
|
@ -31,7 +31,7 @@ class MockClientProxy: ClientProxyProtocol {
|
||||
|
||||
var roomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()
|
||||
|
||||
var messageForwardingRoomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()
|
||||
var alternateRoomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()
|
||||
|
||||
var inviteSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()
|
||||
|
||||
|
@ -34,8 +34,14 @@ struct RoomSummaryDetails {
|
||||
}
|
||||
|
||||
extension RoomSummaryDetails: CustomStringConvertible {
|
||||
var description: String {
|
||||
"RoomSummaryDetails: - id: \(id) - isDirect: \(isDirect) - unreadMessagesCount: \(unreadMessagesCount) - unreadMentionsCount: \(unreadMentionsCount) - unreadNotificationsCount: \(unreadNotificationsCount) - notificationMode: \(notificationMode?.rawValue ?? "nil")"
|
||||
var description: String { """
|
||||
RoomSummaryDetails: - id: \(id) \
|
||||
- isDirect: \(isDirect) \
|
||||
- unreadMessagesCount: \(unreadMessagesCount) \
|
||||
- unreadMentionsCount: \(unreadMentionsCount) \
|
||||
- unreadNotificationsCount: \(unreadNotificationsCount) \
|
||||
- notificationMode: \(notificationMode?.rawValue ?? "nil")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
|
64
UnitTests/Sources/GlobalSearchScreenViewModelTests.swift
Normal file
64
UnitTests/Sources/GlobalSearchScreenViewModelTests.swift
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// 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 XCTest
|
||||
|
||||
@testable import ElementX
|
||||
|
||||
@MainActor
|
||||
class GlobalSearchScreenViewModelTests: XCTestCase {
|
||||
var viewModel: GlobalSearchScreenViewModelProtocol!
|
||||
var context: GlobalSearchScreenViewModelType.Context!
|
||||
var cancellables = Set<AnyCancellable>()
|
||||
|
||||
override func setUpWithError() throws {
|
||||
cancellables.removeAll()
|
||||
viewModel = GlobalSearchScreenViewModel(roomSummaryProvider: MockRoomSummaryProvider(state: .loaded(.mockRooms)),
|
||||
imageProvider: MockMediaProvider())
|
||||
context = viewModel.context
|
||||
}
|
||||
|
||||
func testSearching() async throws {
|
||||
let defered = deferFulfillment(context.$viewState) { state in
|
||||
state.rooms.count == 1
|
||||
}
|
||||
|
||||
context.searchQuery = "Second"
|
||||
|
||||
try await defered.fulfill()
|
||||
}
|
||||
|
||||
func testRoomSelection() {
|
||||
let expectation = expectation(description: "Wait for confirmation")
|
||||
|
||||
viewModel.actions
|
||||
.sink { action in
|
||||
switch action {
|
||||
case .select(let roomID):
|
||||
XCTAssertEqual(roomID, "2")
|
||||
expectation.fulfill()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
context.send(viewAction: .select(roomID: "2"))
|
||||
|
||||
waitForExpectations(timeout: 5.0)
|
||||
}
|
||||
}
|
BIN
UnitTests/__Snapshots__/PreviewTests/test_globalSearchScreen.1.png
(Stored with Git LFS)
Normal file
BIN
UnitTests/__Snapshots__/PreviewTests/test_globalSearchScreen.1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
UnitTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow.1.png
(Stored with Git LFS)
Normal file
BIN
UnitTests/__Snapshots__/PreviewTests/test_globalSearchScreenListRow.1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user