diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 22347bf66..c338e93e2 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -125,7 +125,6 @@ 1C409A26A99F0371C47AFA51 /* UserDiscoveryServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */; }; 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */; }; 1C9BB74711E5F24C77B7FED0 /* RoomMembersListScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */; }; - 1D2B3DBBD2E3F5023C35CB33 /* BadgeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEC0A675E39FAC6AF833DDD /* BadgeLabel.swift */; }; 1D5DC685CED904386C89B7DA /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; 1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; }; 1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; }; @@ -503,6 +502,7 @@ 79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */; }; 7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */; }; 7A170A5A4A352954BB2A1B96 /* AuthenticationStartScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */; }; + 7A25D6926A2C01DB8D0D67A5 /* BadgeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */; }; 7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; }; 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; }; 7A8B264506D3DDABC01B4EEB /* AppMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53AC78E49A297AC1D72A7CF /* AppMediator.swift */; }; @@ -1132,12 +1132,12 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1196,7 +1196,7 @@ 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = ""; }; 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -1284,7 +1284,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1341,7 +1341,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiItem.swift; sourceTree = ""; }; @@ -1674,7 +1674,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = ""; }; 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = ""; }; @@ -1716,6 +1716,7 @@ 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = ""; }; 99637028A8BD2843A35A92D4 /* ResetRecoveryKeyScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetRecoveryKeyScreenViewModelProtocol.swift; sourceTree = ""; }; 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinator.swift; sourceTree = ""; }; + 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeLabel.swift; sourceTree = ""; }; 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationModule.swift; sourceTree = ""; }; 9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = landscape_test_video.mov; sourceTree = ""; }; 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceProtocol.swift; sourceTree = ""; }; @@ -1829,7 +1830,7 @@ B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; @@ -1940,7 +1941,7 @@ CE47A97726F0675DEE387BF9 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = ""; }; CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = ""; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -2061,7 +2062,7 @@ ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = ""; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; @@ -2084,7 +2085,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2129,7 +2130,6 @@ FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattingToolbar.swift; sourceTree = ""; }; FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProtocol.swift; sourceTree = ""; }; FF720BA68256297680980481 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; - FFEC0A675E39FAC6AF833DDD /* BadgeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeLabel.swift; sourceTree = ""; }; FFECCE59967018204876D0A5 /* LocationMarkerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationMarkerView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -2678,9 +2678,9 @@ 328DD5DA1281F758B72006C7 /* Views */ = { isa = PBXGroup; children = ( - FFEC0A675E39FAC6AF833DDD /* BadgeLabel.swift */, 8F21ED7205048668BEB44A38 /* AppActivityView.swift */, CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */, + 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */, C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */, 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */, 7EC2F1622C5BBABED6012E12 /* HeroImage.swift */, @@ -5891,7 +5891,7 @@ 6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */, 4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */, D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */, - 1D2B3DBBD2E3F5023C35CB33 /* BadgeLabel.swift in Sources */, + 7A25D6926A2C01DB8D0D67A5 /* BadgeLabel.swift in Sources */, A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */, 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */, EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */, @@ -6767,7 +6767,9 @@ "@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; @@ -6816,7 +6818,9 @@ "@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)"; @@ -6842,7 +6846,9 @@ "@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)"; @@ -7087,7 +7093,9 @@ "@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; @@ -7304,7 +7312,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.1.65; + version = 1.1.66; }; }; 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d3c347051..566540fea 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -139,8 +139,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "e43f959992d17073436c1068f268c4c1da2d2810", - "version" : "1.1.65" + "revision" : "edfd1bb3c7cb3b11dd91afa0b4c46ea848987a68", + "version" : "1.1.66" } }, { diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 9babf9920..3b76276e2 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -189,11 +189,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg } else { handleAppRoute(.roomMemberDetails(userID: userID)) } - case .room(let roomID): + case .room(let roomID, let via): if isExternalURL { handleAppRoute(route) } else { - handleAppRoute(.childRoom(roomID: roomID)) + handleAppRoute(.childRoom(roomID: roomID, via: via)) } case .roomAlias(let alias): if isExternalURL { @@ -201,17 +201,17 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg } else { handleAppRoute(.childRoomAlias(alias)) } - case .event(let roomID, let eventID): + case .event(let eventID, let roomID, let via): if isExternalURL { handleAppRoute(route) } else { - handleAppRoute(.childEvent(roomID: roomID, eventID: eventID)) + handleAppRoute(.childEvent(eventID: eventID, roomID: roomID, via: via)) } - case .eventOnRoomAlias(let alias, let eventID): + case .eventOnRoomAlias(let eventID, let alias): if isExternalURL { handleAppRoute(route) } else { - handleAppRoute(.childEventOnRoomAlias(alias: alias, eventID: eventID)) + handleAppRoute(.childEventOnRoomAlias(eventID: eventID, alias: alias)) } default: break @@ -267,7 +267,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg return } - handleAppRoute(.room(roomID: roomID)) + handleAppRoute(.room(roomID: roomID, via: [])) } func handleInlineReply(_ service: NotificationManagerProtocol, content: UNNotificationContent, replyText: String) async { diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index abffb1f22..c7ea141d9 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -23,11 +23,11 @@ enum AppRoute: Equatable { /// The app's home screen. case roomList /// A room, shown as the root of the stack (popping any child rooms). - case room(roomID: String) + case room(roomID: String, via: [String]) /// The same as ``room`` but using a room alias. case roomAlias(String) /// A room, pushed as a child of any existing rooms on the stack. - case childRoom(roomID: String) + case childRoom(roomID: String, via: [String]) /// The same as ``childRoom`` but using a room alias. case childRoomAlias(String) /// The information about a particular room. @@ -35,13 +35,13 @@ enum AppRoute: Equatable { /// The profile of a member within the current room. case roomMemberDetails(userID: String) /// An event within a room, shown as the root of the stack (popping any child rooms). - case event(roomID: String, eventID: String) + case event(eventID: String, roomID: String, via: [String]) /// The same as ``event`` but using a room alias. - case eventOnRoomAlias(alias: String, eventID: String) + case eventOnRoomAlias(eventID: String, alias: String) /// An event within a room, either within the last child on the stack or pushing a new child if needed. - case childEvent(roomID: String, eventID: String) + case childEvent(eventID: String, roomID: String, via: [String]) /// The same as ``childEvent`` but using a room alias. - case childEventOnRoomAlias(alias: String, eventID: String) + case childEventOnRoomAlias(eventID: String, alias: String) /// The profile of a matrix user (outside of a room). case userProfile(userID: String) /// An Element Call link generated outside of a chat room. @@ -134,19 +134,19 @@ struct ElementCallURLParser: URLParser { struct MatrixPermalinkParser: URLParser { func route(from url: URL) -> AppRoute? { - switch parseMatrixEntityFrom(uri: url.absoluteString)?.id { + guard let entity = parseMatrixEntityFrom(uri: url.absoluteString) else { return nil } + + switch entity.id { case .room(let id): - return .room(roomID: id) + return .room(roomID: id, via: entity.via) case .roomAlias(let alias): return .roomAlias(alias) case .user(let id): return .userProfile(userID: id) case .eventOnRoomId(let roomID, let eventID): - return .event(roomID: roomID, eventID: eventID) + return .event(eventID: eventID, roomID: roomID, via: entity.via) case .eventOnRoomAlias(let alias, let eventID): - return .eventOnRoomAlias(alias: alias, eventID: eventID) - default: - return nil + return .eventOnRoomAlias(eventID: eventID, alias: alias) } } } diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index d8d2c660a..0ef5e6e31 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -21,14 +21,11 @@ import UserNotifications // swiftlint:disable file_length enum RoomFlowCoordinatorAction: Equatable { - case presentRoom(roomID: String) case presentCallScreen(roomProxy: RoomProxyProtocol) case finished static func == (lhs: RoomFlowCoordinatorAction, rhs: RoomFlowCoordinatorAction) -> Bool { switch (lhs, rhs) { - case (.presentRoom(let lhsRoomID), .presentRoom(let rhsRoomID)): - lhsRoomID == rhsRoomID case (.presentCallScreen(let lhsRoomProxy), .presentCallScreen(let rhsRoomProxy)): lhsRoomProxy.id == rhsRoomProxy.id case (.finished, .finished): @@ -126,15 +123,15 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } switch appRoute { - case .room(let roomID): + case .room(let roomID, let via): Task { - await handleRoomRoute(roomID: roomID, animated: animated) + await handleRoomRoute(roomID: roomID, via: via, animated: animated) } - case .childRoom(let roomID): + case .childRoom(let roomID, let via): if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator { childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated) } else if roomID != roomProxy.id { - stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room), userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: via, entryPoint: .room), userInfo: EventUserInfo(animated: animated)) } else { MXLog.info("Ignoring presentation of the same room as a child of this one.") } @@ -159,13 +156,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } else { stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID), userInfo: EventUserInfo(animated: animated)) } - case .event(let roomID, let eventID): - Task { await handleRoomRoute(roomID: roomID, focussedEventID: eventID, animated: animated) } - case .childEvent(let roomID, let eventID): + case .event(let eventID, let roomID, let via): + Task { await handleRoomRoute(roomID: roomID, via: via, focussedEventID: eventID, animated: animated) } + case .childEvent(let eventID, let roomID, let via): if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator { childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated) } else if roomID != roomProxy.id { - stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: via, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated)) } else { roomScreenCoordinator?.focusOnEvent(eventID: eventID) } @@ -184,11 +181,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) } - private func handleRoomRoute(roomID: String, focussedEventID: String? = nil, animated: Bool) async { + private func handleRoomRoute(roomID: String, via: [String], focussedEventID: String? = nil, animated: Bool) async { guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") } guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else { - stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated)) return } @@ -197,7 +194,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { await storeAndSubscribeToRoomProxy(roomProxy) stateMachine.tryEvent(.presentRoom(focussedEventID: focussedEventID), userInfo: EventUserInfo(animated: animated)) default: - stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated)) } } @@ -343,7 +340,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // Child flow - case (_, .startChildFlow(let roomID, _)): + case (_, .startChildFlow(let roomID, _, _)): return .presentingChild(childRoomID: roomID, previousState: fromState) case (.presentingChild(_, let previousState), .dismissChildFlow): return previousState @@ -359,8 +356,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let animated = (context.userInfo as? EventUserInfo)?.animated ?? true switch (context.fromState, context.event, context.toState) { - case (_, .presentJoinRoomScreen, .joinRoomScreen): - presentJoinRoomScreen(animated: true) + case (_, .presentJoinRoomScreen(let via), .joinRoomScreen): + presentJoinRoomScreen(via: via, animated: true) case (_, .dismissJoinRoomScreen, .complete): dismissFlow(animated: animated) @@ -474,8 +471,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { rolesAndPermissionsFlowCoordinator = nil // Child flow - case (_, .startChildFlow(let roomID, let entryPoint), .presentingChild): - Task { await self.startChildFlow(for: roomID, entryPoint: entryPoint) } + case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild): + Task { await self.startChildFlow(for: roomID, via: via, entryPoint: entryPoint) } case (.presentingChild, .dismissChildFlow, _): childRoomFlowCoordinator = nil @@ -612,8 +609,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } - private func presentJoinRoomScreen(animated: Bool) { + private func presentJoinRoomScreen(via: [String], animated: Bool) { let coordinator = JoinRoomScreenCoordinator(parameters: .init(roomID: roomID, + via: via, clientProxy: userSession.clientProxy, mediaProvider: userSession.mediaProvider, userIndicatorController: userIndicatorController)) @@ -1073,7 +1071,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case .openUserProfile: stateMachine.tryEvent(.presentUserProfile(userID: userID)) case .openDirectChat(let roomID): - stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room)) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) case .startCall(let roomID): Task { await self.presentCallScreen(roomID: roomID) } } @@ -1098,7 +1096,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { switch action { case .openDirectChat(let roomID): - stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room)) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) case .startCall(let roomID): Task { await self.presentCallScreen(roomID: roomID) } case .dismiss: @@ -1140,7 +1138,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case .sent(let roomID): navigationStackCoordinator.setSheetCoordinator(nil) // Timelines are cached - the local echo will be visible when fetching the room by its ID. - stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room)) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) } } .store(in: &cancellables) @@ -1283,7 +1281,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // MARK: - Child Flow - private func startChildFlow(for roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint) async { + private func startChildFlow(for roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) async { let coordinator = await RoomFlowCoordinator(roomID: roomID, userSession: userSession, isChildFlow: true, @@ -1298,8 +1296,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { - case .presentRoom(let roomID): - actionsSubject.send(.presentRoom(roomID: roomID)) case .presentCallScreen(let roomProxy): actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) case .finished: @@ -1311,9 +1307,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { childRoomFlowCoordinator = coordinator switch entryPoint { case .room: - coordinator.handleAppRoute(.room(roomID: roomID), animated: true) + coordinator.handleAppRoute(.room(roomID: roomID, via: via), animated: true) case .eventID(let eventID): - coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: true) + coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: true) case .roomDetails: coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: true) } @@ -1367,7 +1363,7 @@ private extension RoomFlowCoordinator { } enum Event: EventType { - case presentJoinRoomScreen + case presentJoinRoomScreen(via: [String]) case dismissJoinRoomScreen case presentRoom(focussedEventID: String?) @@ -1425,7 +1421,7 @@ private extension RoomFlowCoordinator { case dismissRolesAndPermissionsScreen // Child room flow events - case startChildFlow(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint) + case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) case dismissChildFlow } } diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 82474a938..b94c10f87 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -200,40 +200,40 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { await clearPresentedSheets(animated: animated) switch appRoute { - case .room(let roomID): - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated)) + case .room(let roomID, let via): + stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .room), userInfo: .init(animated: animated)) case .roomAlias(let alias): - guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return } - await asyncHandleAppRoute(.room(roomID: roomID), animated: animated) - case .childRoom(let roomID): + guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return } + await asyncHandleAppRoute(.room(roomID: resolved.roomId, via: resolved.servers), animated: animated) + case .childRoom(let roomID, let via): if let roomFlowCoordinator { roomFlowCoordinator.handleAppRoute(appRoute, animated: animated) } else { - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated)) + stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .room), userInfo: .init(animated: animated)) } case .childRoomAlias(let alias): - guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return } - await asyncHandleAppRoute(.childRoom(roomID: roomID), animated: animated) + guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return } + await asyncHandleAppRoute(.childRoom(roomID: resolved.roomId, via: resolved.servers), animated: animated) case .roomDetails(let roomID): if stateMachine.state.selectedRoomID == roomID { roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated) } else { - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .roomDetails), userInfo: .init(animated: animated)) + stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .roomDetails), userInfo: .init(animated: animated)) } case .roomList: roomFlowCoordinator?.clearRoute(animated: animated) case .roomMemberDetails: roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated) - case .event(let roomID, let eventID): - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: .init(animated: animated)) - case .eventOnRoomAlias(let alias, let eventID): - guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return } - await asyncHandleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated) + case .event(let eventID, let roomID, let via): + stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .eventID(eventID)), userInfo: .init(animated: animated)) + case .eventOnRoomAlias(let eventID, let alias): + guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return } + await asyncHandleAppRoute(.event(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated) case .childEvent: roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated) - case .childEventOnRoomAlias(let alias, let eventID): - guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return } - await asyncHandleAppRoute(.childEvent(roomID: roomID, eventID: eventID), animated: animated) + case .childEventOnRoomAlias(let eventID, let alias): + guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return } + await asyncHandleAppRoute(.childEvent(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated) case .userProfile(let userID): stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated)) case .genericCallLink(let url): @@ -271,18 +271,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case (.initial, .start, .roomList): presentHomeScreen() attemptStartingOnboarding() - case(.roomList(let selectedRoomID), .selectRoom(let roomID, let entryPoint), .roomList): + case(.roomList(let selectedRoomID), .selectRoom(let roomID, let via, let entryPoint), .roomList): if selectedRoomID == roomID, !entryPoint.isEventID, // Don't reuse the existing room so the live timeline is hidden while the detached timeline is loading. let roomFlowCoordinator { let route: AppRoute = switch entryPoint { - case .room: .room(roomID: roomID) + case .room: .room(roomID: roomID, via: via) case .roomDetails: .roomDetails(roomID: roomID) - case .eventID(let eventID): .event(roomID: roomID, eventID: eventID) // ignored. + case .eventID(let eventID): .event(eventID: eventID, roomID: roomID, via: via) // ignored. } roomFlowCoordinator.handleAppRoute(route, animated: animated) } else { - Task { await self.startRoomFlow(roomID: roomID, entryPoint: entryPoint, animated: animated) } + Task { await self.startRoomFlow(roomID: roomID, via: via, entryPoint: entryPoint, animated: animated) } } case(.roomList, .deselectRoom, .roomList): dismissRoomFlow(animated: animated) @@ -359,7 +359,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { switch action { case .presentRoom(let roomID): - handleAppRoute(.room(roomID: roomID), animated: true) + handleAppRoute(.room(roomID: roomID, via: []), animated: true) case .presentRoomDetails(let roomID): handleAppRoute(.roomDetails(roomID: roomID), animated: true) case .roomLeft(let roomID): @@ -438,6 +438,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { // MARK: Room Flow private func startRoomFlow(roomID: String, + via: [String], entryPoint: RoomFlowCoordinatorEntryPoint, animated: Bool) async { let coordinator = await RoomFlowCoordinator(roomID: roomID, @@ -455,12 +456,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { - case .finished: - stateMachine.processEvent(.deselectRoom) - case .presentRoom(let roomID): - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room)) case .presentCallScreen(let roomProxy): presentCallScreen(roomProxy: roomProxy) + case .finished: + stateMachine.processEvent(.deselectRoom) } } .store(in: &cancellables) @@ -473,9 +472,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { switch entryPoint { case .room: - coordinator.handleAppRoute(.room(roomID: roomID), animated: animated) + coordinator.handleAppRoute(.room(roomID: roomID, via: via), animated: animated) case .eventID(let eventID): - coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated) + coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: animated) case .roomDetails: coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: animated) } @@ -513,7 +512,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { self.navigationSplitCoordinator.setSheetCoordinator(nil) case .openRoom(let roomID): self.navigationSplitCoordinator.setSheetCoordinator(nil) - self.stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room)) + self.stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room)) } } .store(in: &cancellables) @@ -597,7 +596,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { dismissGlobalSearch() case .select(let roomID): dismissGlobalSearch() - handleAppRoute(.room(roomID: roomID), animated: true) + handleAppRoute(.room(roomID: roomID, via: []), animated: true) } } .store(in: &cancellables) @@ -627,9 +626,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { guard let self else { return } switch action { - case .select(let roomID): + case .selectAlias(let alias): stateMachine.processEvent(.dismissedRoomDirectorySearchScreen) - handleAppRoute(.room(roomID: roomID), animated: true) + handleAppRoute(.roomAlias(alias), animated: true) + case .selectRoomID(let roomID): + stateMachine.processEvent(.dismissedRoomDirectorySearchScreen) + handleAppRoute(.room(roomID: roomID, via: []), animated: true) case .dismiss: stateMachine.processEvent(.dismissedRoomDirectorySearchScreen) } @@ -662,7 +664,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { switch action { case .openDirectChat(let roomID): navigationSplitCoordinator.setSheetCoordinator(nil) - stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room)) + stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room)) case .startCall(let roomID): Task { await self.presentCallScreen(roomID: roomID) } case .dismiss: diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift index d5a779f61..78afe9de9 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift @@ -70,10 +70,11 @@ class UserSessionFlowCoordinatorStateMachine { /// Start the user session flows. case start - /// Request presentation for a particular room - /// - Parameter roomID: The room identifier + /// Request presentation for a particular room. + /// - Parameter roomID: The room identifier. + /// - Parameter via: Any servers necessary to discover the room. /// - Parameter entryPoint: The starting point for the presented room. - case selectRoom(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint) + case selectRoom(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) /// The room screen has been dismissed case deselectRoom @@ -129,7 +130,7 @@ class UserSessionFlowCoordinatorStateMachine { stateMachine.addRouteMapping { event, fromState, _ in switch (fromState, event) { - case (.roomList, .selectRoom(let roomID, _)): + case (.roomList, .selectRoom(let roomID, _, _)): return .roomList(selectedRoomID: roomID) case (.roomList, .deselectRoom): return .roomList(selectedRoomID: nil) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 8b60273d8..866ef644f 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -2428,15 +2428,15 @@ class ClientProxyMock: ClientProxyProtocol { } //MARK: - joinRoom - var joinRoomUnderlyingCallsCount = 0 - var joinRoomCallsCount: Int { + var joinRoomViaUnderlyingCallsCount = 0 + var joinRoomViaCallsCount: Int { get { if Thread.isMainThread { - return joinRoomUnderlyingCallsCount + return joinRoomViaUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = joinRoomUnderlyingCallsCount + returnValue = joinRoomViaUnderlyingCallsCount } return returnValue! @@ -2444,29 +2444,29 @@ class ClientProxyMock: ClientProxyProtocol { } set { if Thread.isMainThread { - joinRoomUnderlyingCallsCount = newValue + joinRoomViaUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - joinRoomUnderlyingCallsCount = newValue + joinRoomViaUnderlyingCallsCount = newValue } } } } - var joinRoomCalled: Bool { - return joinRoomCallsCount > 0 + var joinRoomViaCalled: Bool { + return joinRoomViaCallsCount > 0 } - var joinRoomReceivedRoomID: String? - var joinRoomReceivedInvocations: [String] = [] + var joinRoomViaReceivedArguments: (roomID: String, via: [String])? + var joinRoomViaReceivedInvocations: [(roomID: String, via: [String])] = [] - var joinRoomUnderlyingReturnValue: Result! - var joinRoomReturnValue: Result! { + var joinRoomViaUnderlyingReturnValue: Result! + var joinRoomViaReturnValue: Result! { get { if Thread.isMainThread { - return joinRoomUnderlyingReturnValue + return joinRoomViaUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = joinRoomUnderlyingReturnValue + returnValue = joinRoomViaUnderlyingReturnValue } return returnValue! @@ -2474,24 +2474,24 @@ class ClientProxyMock: ClientProxyProtocol { } set { if Thread.isMainThread { - joinRoomUnderlyingReturnValue = newValue + joinRoomViaUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - joinRoomUnderlyingReturnValue = newValue + joinRoomViaUnderlyingReturnValue = newValue } } } } - var joinRoomClosure: ((String) async -> Result)? + var joinRoomViaClosure: ((String, [String]) async -> Result)? - func joinRoom(_ roomID: String) async -> Result { - joinRoomCallsCount += 1 - joinRoomReceivedRoomID = roomID - joinRoomReceivedInvocations.append(roomID) - if let joinRoomClosure = joinRoomClosure { - return await joinRoomClosure(roomID) + func joinRoom(_ roomID: String, via: [String]) async -> Result { + joinRoomViaCallsCount += 1 + joinRoomViaReceivedArguments = (roomID: roomID, via: via) + joinRoomViaReceivedInvocations.append((roomID: roomID, via: via)) + if let joinRoomViaClosure = joinRoomViaClosure { + return await joinRoomViaClosure(roomID, via) } else { - return joinRoomReturnValue + return joinRoomViaReturnValue } } //MARK: - uploadMedia @@ -3431,13 +3431,13 @@ class ClientProxyMock: ClientProxyProtocol { var resolveRoomAliasReceivedAlias: String? var resolveRoomAliasReceivedInvocations: [String] = [] - var resolveRoomAliasUnderlyingReturnValue: String? - var resolveRoomAliasReturnValue: String? { + var resolveRoomAliasUnderlyingReturnValue: ResolvedRoomAlias? + var resolveRoomAliasReturnValue: ResolvedRoomAlias? { get { if Thread.isMainThread { return resolveRoomAliasUnderlyingReturnValue } else { - var returnValue: String?? = nil + var returnValue: ResolvedRoomAlias?? = nil DispatchQueue.main.sync { returnValue = resolveRoomAliasUnderlyingReturnValue } @@ -3455,9 +3455,9 @@ class ClientProxyMock: ClientProxyProtocol { } } } - var resolveRoomAliasClosure: ((String) async -> String?)? + var resolveRoomAliasClosure: ((String) async -> ResolvedRoomAlias?)? - func resolveRoomAlias(_ alias: String) async -> String? { + func resolveRoomAlias(_ alias: String) async -> ResolvedRoomAlias? { resolveRoomAliasCallsCount += 1 resolveRoomAliasReceivedAlias = alias resolveRoomAliasReceivedInvocations.append(alias) diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 6e508301a..62e54f4b3 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -1480,6 +1480,78 @@ class SDKClientMock: SDKClientProtocol { return joinRoomByIdRoomIdReturnValue } } + //MARK: - joinRoomByIdOrAlias + + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesThrowableError: Error? + var joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingCallsCount = 0 + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesCallsCount: Int { + get { + if Thread.isMainThread { + return joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingCallsCount = newValue + } + } + } + } + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesCalled: Bool { + return joinRoomByIdOrAliasRoomIdOrAliasServerNamesCallsCount > 0 + } + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesReceivedArguments: (roomIdOrAlias: String, serverNames: [String])? + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesReceivedInvocations: [(roomIdOrAlias: String, serverNames: [String])] = [] + + var joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingReturnValue: Room! + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesReturnValue: Room! { + get { + if Thread.isMainThread { + return joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingReturnValue + } else { + var returnValue: Room? = nil + DispatchQueue.main.sync { + returnValue = joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + joinRoomByIdOrAliasRoomIdOrAliasServerNamesUnderlyingReturnValue = newValue + } + } + } + } + public var joinRoomByIdOrAliasRoomIdOrAliasServerNamesClosure: ((String, [String]) async throws -> Room)? + + public func joinRoomByIdOrAlias(roomIdOrAlias: String, serverNames: [String]) async throws -> Room { + if let error = joinRoomByIdOrAliasRoomIdOrAliasServerNamesThrowableError { + throw error + } + joinRoomByIdOrAliasRoomIdOrAliasServerNamesCallsCount += 1 + joinRoomByIdOrAliasRoomIdOrAliasServerNamesReceivedArguments = (roomIdOrAlias: roomIdOrAlias, serverNames: serverNames) + joinRoomByIdOrAliasRoomIdOrAliasServerNamesReceivedInvocations.append((roomIdOrAlias: roomIdOrAlias, serverNames: serverNames)) + if let joinRoomByIdOrAliasRoomIdOrAliasServerNamesClosure = joinRoomByIdOrAliasRoomIdOrAliasServerNamesClosure { + return try await joinRoomByIdOrAliasRoomIdOrAliasServerNamesClosure(roomIdOrAlias, serverNames) + } else { + return joinRoomByIdOrAliasRoomIdOrAliasServerNamesReturnValue + } + } //MARK: - login public var loginUsernamePasswordInitialDeviceNameDeviceIdThrowableError: Error? @@ -1735,13 +1807,13 @@ class SDKClientMock: SDKClientProtocol { public var resolveRoomAliasRoomAliasReceivedRoomAlias: String? public var resolveRoomAliasRoomAliasReceivedInvocations: [String] = [] - var resolveRoomAliasRoomAliasUnderlyingReturnValue: String! - public var resolveRoomAliasRoomAliasReturnValue: String! { + var resolveRoomAliasRoomAliasUnderlyingReturnValue: ResolvedRoomAlias! + public var resolveRoomAliasRoomAliasReturnValue: ResolvedRoomAlias! { get { if Thread.isMainThread { return resolveRoomAliasRoomAliasUnderlyingReturnValue } else { - var returnValue: String? = nil + var returnValue: ResolvedRoomAlias? = nil DispatchQueue.main.sync { returnValue = resolveRoomAliasRoomAliasUnderlyingReturnValue } @@ -1759,9 +1831,9 @@ class SDKClientMock: SDKClientProtocol { } } } - public var resolveRoomAliasRoomAliasClosure: ((String) async throws -> String)? + public var resolveRoomAliasRoomAliasClosure: ((String) async throws -> ResolvedRoomAlias)? - public func resolveRoomAlias(roomAlias: String) async throws -> String { + public func resolveRoomAlias(roomAlias: String) async throws -> ResolvedRoomAlias { if let error = resolveRoomAliasRoomAliasThrowableError { throw error } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift index b2b91b86c..e3ba955ce 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift @@ -19,6 +19,7 @@ import SwiftUI struct JoinRoomScreenCoordinatorParameters { let roomID: String + let via: [String] let clientProxy: ClientProxyProtocol let mediaProvider: MediaProviderProtocol let userIndicatorController: UserIndicatorControllerProtocol @@ -44,6 +45,7 @@ final class JoinRoomScreenCoordinator: CoordinatorProtocol { self.parameters = parameters viewModel = JoinRoomScreenViewModel(roomID: parameters.roomID, + via: parameters.via, clientProxy: parameters.clientProxy, mediaProvider: parameters.mediaProvider, userIndicatorController: parameters.userIndicatorController) diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 12b4b488c..0f45c066f 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -21,6 +21,7 @@ typealias JoinRoomScreenViewModelType = StateStoreViewModel Result { + func joinRoom(_ roomID: String, via: [String]) async -> Result { do { - let _ = try await client.joinRoomById(roomId: roomID) + let _ = try await client.joinRoomByIdOrAlias(roomIdOrAlias: roomID, serverNames: via) // Wait for the room to appear in the room lists to avoid issues downstream let _ = await waitForRoomSummary(with: .success(roomID), name: nil, timeout: 30) @@ -569,7 +569,7 @@ class ClientProxy: ClientProxyProtocol { RoomDirectorySearchProxy(roomDirectorySearch: client.roomDirectorySearch()) } - func resolveRoomAlias(_ alias: String) async -> String? { + func resolveRoomAlias(_ alias: String) async -> ResolvedRoomAlias? { do { return try await client.resolveRoomAlias(roomAlias: alias) } catch { @@ -678,7 +678,6 @@ class ClientProxy: ClientProxyProtocol { .syncService() .withCrossProcessLock(appIdentifier: "MainApp") .withUtdHook(delegate: ClientDecryptionErrorDelegate(actionsSubject: actionsSubject)) - .withUnifiedInvitesInRoomList(withUnifiedInvites: true) .finish() let roomListService = syncService.roomListService() diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 5f47c3ef6..7e2d6126a 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -129,7 +129,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func createRoom(name: String, topic: String?, isRoomPrivate: Bool, userIDs: [String], avatarURL: URL?) async -> Result - func joinRoom(_ roomID: String) async -> Result + func joinRoom(_ roomID: String, via: [String]) async -> Result func uploadMedia(_ media: MediaInfo) async -> Result @@ -159,7 +159,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func roomDirectorySearchProxy() -> RoomDirectorySearchProxyProtocol - func resolveRoomAlias(_ alias: String) async -> String? + func resolveRoomAlias(_ alias: String) async -> ResolvedRoomAlias? // MARK: - Ignored users diff --git a/UnitTests/Sources/AppRouteURLParserTests.swift b/UnitTests/Sources/AppRouteURLParserTests.swift index 0efeebe09..76b2378f6 100644 --- a/UnitTests/Sources/AppRouteURLParserTests.swift +++ b/UnitTests/Sources/AppRouteURLParserTests.swift @@ -130,7 +130,7 @@ class AppRouteURLParserTests: XCTestCase { let route = appRouteURLParser.route(from: url) - XCTAssertEqual(route, .room(roomID: id)) + XCTAssertEqual(route, .room(roomID: id, via: [])) } func testWebRoomIDURL() { @@ -142,7 +142,7 @@ class AppRouteURLParserTests: XCTestCase { let route = appRouteURLParser.route(from: url) - XCTAssertEqual(route, .room(roomID: id)) + XCTAssertEqual(route, .room(roomID: id, via: [])) } func testWebUserIDURL() { diff --git a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift index 36c63e8bd..226f1d9e3 100644 --- a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift +++ b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift @@ -55,7 +55,7 @@ class JoinRoomScreenViewModelTests: XCTestCase { private func setupViewModel(throwing: Bool = false) { let clientProxy = ClientProxyMock(.init()) - clientProxy.joinRoomReturnValue = throwing ? .failure(.sdkError(ClientProxyMockError.generic)) : .success(()) + clientProxy.joinRoomViaReturnValue = throwing ? .failure(.sdkError(ClientProxyMockError.generic)) : .success(()) clientProxy.roomPreviewForIdentifierReturnValue = .success(.init(roomID: "", name: nil, @@ -70,6 +70,7 @@ class JoinRoomScreenViewModelTests: XCTestCase { canKnock: false)) viewModel = JoinRoomScreenViewModel(roomID: "1", + via: [], clientProxy: clientProxy, mediaProvider: MockMediaProvider(), userIndicatorController: ServiceLocator.shared.userIndicatorController) diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 02315d661..3c3d192ff 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -30,7 +30,7 @@ class RoomFlowCoordinatorTests: XCTestCase { func testRoomPresentation() async throws { await setupRoomFlowCoordinator() - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) try await clearRoute(expectedActions: [.finished]) @@ -64,7 +64,7 @@ class RoomFlowCoordinatorTests: XCTestCase { func testPushDetails() async throws { await setupRoomFlowCoordinator() - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) @@ -77,15 +77,15 @@ class RoomFlowCoordinatorTests: XCTestCase { func testChildRoomFlow() async throws { await setupRoomFlowCoordinator() - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) - try await process(route: .childRoom(roomID: "2")) + try await process(route: .childRoom(roomID: "2", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) - try await process(route: .childRoom(roomID: "3")) + try await process(route: .childRoom(roomID: "3", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 2) XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) XCTAssert(navigationStackCoordinator.stackCoordinators.last is RoomScreenCoordinator) @@ -100,7 +100,7 @@ class RoomFlowCoordinatorTests: XCTestCase { await setupRoomFlowCoordinator(asChildFlow: true) navigationStackCoordinator.setRootCoordinator(BlankFormCoordinator()) - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) try await process(route: .roomDetails(roomID: "1")) XCTAssertTrue(navigationStackCoordinator.rootCoordinator is BlankFormCoordinator, "A child room flow should push onto the stack, leaving the root alone.") XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 2) @@ -117,11 +117,11 @@ class RoomFlowCoordinatorTests: XCTestCase { func testChildRoomMemberDetails() async throws { await setupRoomFlowCoordinator() - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) - try await process(route: .childRoom(roomID: "2")) + try await process(route: .childRoom(roomID: "2", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) @@ -134,19 +134,19 @@ class RoomFlowCoordinatorTests: XCTestCase { func testChildRoomIgnoresDirectDuplicate() async throws { await setupRoomFlowCoordinator() - try await process(route: .room(roomID: "1")) + try await process(route: .room(roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) - try await process(route: .childRoom(roomID: "1")) + try await process(route: .childRoom(roomID: "1", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0, "A room flow shouldn't present a direct child for the same room.") - try await process(route: .childRoom(roomID: "2")) + try await process(route: .childRoom(roomID: "2", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) - try await process(route: .childRoom(roomID: "1")) + try await process(route: .childRoom(roomID: "1", via: [])) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 2, "Presenting the same room multiple times should be allowed when it's not a direct child of itself.") XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) @@ -156,7 +156,7 @@ class RoomFlowCoordinatorTests: XCTestCase { func testRoomMembershipInvite() async throws { await setupRoomFlowCoordinator(roomType: .invited(roomID: "InvitedRoomID")) - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is JoinRoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) @@ -165,7 +165,7 @@ class RoomFlowCoordinatorTests: XCTestCase { await setupRoomFlowCoordinator(roomType: .invited(roomID: "InvitedRoomID")) - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is JoinRoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) @@ -174,7 +174,7 @@ class RoomFlowCoordinatorTests: XCTestCase { RoomProxyMock(with: .init()) } - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) } @@ -183,7 +183,7 @@ class RoomFlowCoordinatorTests: XCTestCase { await setupRoomFlowCoordinator(asChildFlow: true, roomType: .invited(roomID: "InvitedRoomID")) navigationStackCoordinator.setRootCoordinator(BlankFormCoordinator()) - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssertTrue(navigationStackCoordinator.rootCoordinator is BlankFormCoordinator, "A child room flow should push onto the stack, leaving the root alone.") XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssertTrue(navigationStackCoordinator.stackCoordinators.last is JoinRoomScreenCoordinator) @@ -194,7 +194,7 @@ class RoomFlowCoordinatorTests: XCTestCase { await setupRoomFlowCoordinator(asChildFlow: true, roomType: .invited(roomID: "InvitedRoomID")) navigationStackCoordinator.setRootCoordinator(BlankFormCoordinator()) - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssertTrue(navigationStackCoordinator.rootCoordinator is BlankFormCoordinator, "A child room flow should push onto the stack, leaving the root alone.") XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssertTrue(navigationStackCoordinator.stackCoordinators.last is JoinRoomScreenCoordinator) @@ -204,7 +204,7 @@ class RoomFlowCoordinatorTests: XCTestCase { RoomProxyMock(with: .init()) } - try await process(route: .room(roomID: "InvitedRoomID")) + try await process(route: .room(roomID: "InvitedRoomID", via: [])) XCTAssertTrue(navigationStackCoordinator.rootCoordinator is BlankFormCoordinator, "A child room flow should push onto the stack, leaving the root alone.") XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssertTrue(navigationStackCoordinator.stackCoordinators.last is RoomScreenCoordinator) @@ -213,15 +213,15 @@ class RoomFlowCoordinatorTests: XCTestCase { func testEventRoute() async throws { await setupRoomFlowCoordinator() - try await process(route: .event(roomID: "1", eventID: "1")) + try await process(route: .event(eventID: "1", roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) - try await process(route: .childEvent(roomID: "1", eventID: "2")) + try await process(route: .childEvent(eventID: "2", roomID: "1", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) - try await process(route: .childEvent(roomID: "2", eventID: "3")) + try await process(route: .childEvent(eventID: "3", roomID: "2", via: [])) XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) diff --git a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift index 5e788b249..60df45782 100644 --- a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift +++ b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift @@ -64,7 +64,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { } func testRoomPresentation() async throws { - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) @@ -72,11 +72,11 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertNil(detailNavigationStack?.rootCoordinator) XCTAssertNil(detailCoordinator) - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) - try await process(route: .room(roomID: "2"), expectedState: .roomList(selectedRoomID: "2")) + try await process(route: .room(roomID: "2", via: []), expectedState: .roomList(selectedRoomID: "2")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) @@ -88,7 +88,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { } func testRoomAliasPresentation() async throws { - clientProxy.resolveRoomAliasReturnValue = "1" + clientProxy.resolveRoomAliasReturnValue = .init(roomId: "1", servers: []) try await process(route: .roomAlias("#alias:matrix.org"), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) @@ -98,13 +98,13 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertNil(detailNavigationStack?.rootCoordinator) XCTAssertNil(detailCoordinator) - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) - clientProxy.resolveRoomAliasReturnValue = "2" + clientProxy.resolveRoomAliasReturnValue = .init(roomId: "2", servers: []) - try await process(route: .room(roomID: "2"), expectedState: .roomList(selectedRoomID: "2")) + try await process(route: .room(roomID: "2", via: []), expectedState: .roomList(selectedRoomID: "2")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) @@ -130,7 +130,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomDetailsScreenCoordinator) XCTAssertNotNil(detailCoordinator) - try await process(route: .room(roomID: "2"), expectedState: .roomList(selectedRoomID: "2")) + try await process(route: .room(roomID: "2", via: []), expectedState: .roomList(selectedRoomID: "2")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) } @@ -159,7 +159,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { } func testPushDetails() async throws { - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) @@ -178,7 +178,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomDetailsScreenCoordinator) XCTAssertNotNil(detailCoordinator) - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) } @@ -199,19 +199,19 @@ class UserSessionFlowCoordinatorTests: XCTestCase { } func testRoomClearsStack() async throws { - try await process(route: .room(roomID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .room(roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) - userSessionFlowCoordinator.handleAppRoute(.childRoom(roomID: "2"), animated: true) + userSessionFlowCoordinator.handleAppRoute(.childRoom(roomID: "2", via: []), animated: true) try await Task.sleep(for: .milliseconds(100)) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1) XCTAssertTrue(detailNavigationStack?.stackCoordinators.first is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) - try await process(route: .room(roomID: "3"), expectedState: .roomList(selectedRoomID: "3")) + try await process(route: .room(roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) @@ -219,7 +219,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { func testEventRoutes() async throws { // A regular event route should set its room as the root of the stack and focus on the event. - try await process(route: .event(roomID: "1", eventID: "1"), expectedState: .roomList(selectedRoomID: "1")) + try await process(route: .event(eventID: "1", roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) @@ -227,7 +227,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "1") // A child event route should push a new room screen onto the stack and focus on the event. - userSessionFlowCoordinator.handleAppRoute(.childEvent(roomID: "2", eventID: "2"), animated: true) + userSessionFlowCoordinator.handleAppRoute(.childEvent(eventID: "2", roomID: "2", via: []), animated: true) try await Task.sleep(for: .milliseconds(100)) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1) @@ -237,7 +237,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "2") // A subsequent regular event route should clear the stack and set the new room as the root of the stack. - try await process(route: .event(roomID: "3", eventID: "3"), expectedState: .roomList(selectedRoomID: "3")) + try await process(route: .event(eventID: "3", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) @@ -245,7 +245,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "3") // A regular event route for the same room should set a new instance of the room as the root of the stack. - try await process(route: .event(roomID: "3", eventID: "4"), expectedState: .roomList(selectedRoomID: "3")) + try await process(route: .event(eventID: "4", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) diff --git a/project.yml b/project.yml index 0a86df0b0..ae24e04a6 100644 --- a/project.yml +++ b/project.yml @@ -49,7 +49,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 1.1.65 + exactVersion: 1.1.66 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios