From 334df3f5cd9a4c26ffd61ddc501a4ac1f9a6802e Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:00:20 +0000 Subject: [PATCH] Rename SpaceRoomProxy to SpaceServiceRoom and stop proxying the struct. (#4952) * Rename SpaceRoomProxy to SpaceServiceRoom. The underlying type is a struct, we don't need to proxy it. * Actually stop proxying the SpaceRoom. --- ElementX.xcodeproj/project.pbxproj | 24 +- .../SpaceFlowCoordinator.swift | 12 +- ElementX/Sources/Mocks/ClientProxyMock.swift | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 122 +++++------ .../Sources/Mocks/RoomPreviewProxyMock.swift | 20 +- .../Mocks/SDK/LeaveSpaceHandleSDKMock.swift | 16 +- .../Sources/Mocks/SpaceRoomInfoMock.swift | 205 ++++++++++++++++++ .../Mocks/SpaceRoomListProxyMock.swift | 20 +- .../Sources/Mocks/SpaceRoomProxyMock.swift | 205 ------------------ .../Sources/Mocks/SpaceServiceProxyMock.swift | 12 +- .../JoinRoomScreenCoordinator.swift | 6 +- .../JoinRoomScreen/JoinRoomScreenModels.swift | 2 +- .../JoinRoomScreenViewModel.swift | 34 +-- .../JoinRoomScreen/View/JoinRoomScreen.swift | 2 +- .../ManageAuthorizedSpacesScreenModels.swift | 2 +- .../View/ManageAuthorizedSpacesScreen.swift | 2 +- .../SecurityAndPrivacyScreenModels.swift | 4 +- .../SecurityAndPrivacyScreenViewModel.swift | 4 +- .../View/SecurityAndPrivacyScreen.swift | 8 +- .../Spaces/Common/SpaceHeaderView.swift | 80 +++---- .../Screens/Spaces/Common/SpaceRoomCell.swift | 38 ++-- .../View/LeaveSpaceRoomDetailsCell.swift | 46 ++-- .../LeaveSpace/View/LeaveSpaceView.swift | 28 +-- .../SpaceListScreenModels.swift | 2 +- .../SpaceListScreenViewModel.swift | 8 +- .../View/SpaceListScreen.swift | 6 +- .../SpaceScreen/SpaceScreenCoordinator.swift | 6 +- .../SpaceScreen/SpaceScreenModels.swift | 6 +- .../SpaceScreen/SpaceScreenViewModel.swift | 32 +-- .../Spaces/SpaceScreen/View/SpaceScreen.swift | 30 +-- .../Spaces/LeaveSpaceHandleProxy.swift | 14 +- .../Services/Spaces/SpaceRoomListProxy.swift | 32 +-- .../Spaces/SpaceRoomListProxyProtocol.swift | 4 +- .../Services/Spaces/SpaceRoomProxy.swift | 38 ---- .../Services/Spaces/SpaceServiceProxy.swift | 24 +- .../Spaces/SpaceServiceProxyProtocol.swift | 6 +- .../Services/Spaces/SpaceServiceRoom.swift | 54 +++++ ...l.swift => SpaceServiceRoomProtocol.swift} | 8 +- .../UITests/UITestsAppCoordinator.swift | 2 +- .../Sources/HomeScreenViewModelTests.swift | 4 +- ...curityAndPrivacyScreenViewModelTests.swift | 22 +- .../SpaceListScreenViewModelTests.swift | 14 +- .../Sources/SpaceScreenViewModelTests.swift | 16 +- 43 files changed, 620 insertions(+), 604 deletions(-) create mode 100644 ElementX/Sources/Mocks/SpaceRoomInfoMock.swift delete mode 100644 ElementX/Sources/Mocks/SpaceRoomProxyMock.swift delete mode 100644 ElementX/Sources/Services/Spaces/SpaceRoomProxy.swift create mode 100644 ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift rename ElementX/Sources/Services/Spaces/{SpaceRoomProxyProtocol.swift => SpaceServiceRoomProtocol.swift} (90%) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 190bc866b..2d333e2ff 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -216,7 +216,6 @@ 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; }; 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; }; 24C32D7EF94ECF9081638DF6 /* RemotePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A05E85E4872C3221C5C287 /* RemotePreference.swift */; }; - 24D4E0BBC2ECD2AAD84E7159 /* SpaceRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */; }; 250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11397904D19CFF0E3689F0E /* SpaceScreenModels.swift */; }; 2538350683F421AB620AA950 /* AccessibleLongPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307C3E5B9B189497D3250E23 /* AccessibleLongPress.swift */; }; 25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; }; @@ -540,6 +539,7 @@ 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; }; 60ED66E63A169E47489348A8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; 611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */; }; + 612196AF7826846A50C07FA6 /* SpaceServiceRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */; }; 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; }; 6183BD3916CAA7134B6070D2 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */; }; @@ -826,6 +826,7 @@ 90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE40D4A5DD857AC16EED945A /* URLSession.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; + 913BCABB99796F82E3D8D93D /* SpaceRoomInfoMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5530D3541C8832D858EB755A /* SpaceRoomInfoMock.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; @@ -1079,7 +1080,6 @@ BDED6DA7AD1E76018C424143 /* LegalInformationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C34667458773B02AB5FB0B2 /* LegalInformationScreenViewModel.swift */; }; BDFF0AEBF57B5B124062DAEF /* GeneratedAccessibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CEB4590CCF70F0E3C0B171 /* GeneratedAccessibilityTests.swift */; }; BE011C4473B9A8F12CBFE92A /* UserDetailsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F58D94C936A1B731D78DE1 /* UserDetailsEditScreenViewModelTests.swift */; }; - BE8075CA131C5EA3665C9E0D /* SpaceRoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01F2E9FD8FF95AB89A345E6 /* SpaceRoomProxyProtocol.swift */; }; BE8E5985771DF9137C6CE89A /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */; }; BEC6DFEA506085D3027E353C /* MediaEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */; }; BED59052E5C5163D2B065CA6 /* EventTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A81FD0C60175FA081EB19AD /* EventTimelineItem.swift */; }; @@ -1127,7 +1127,6 @@ C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; }; C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */; }; C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; }; - C73CF79A578133D3AB7FB83D /* SpaceRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF771312D208C8002A2F05C4 /* SpaceRoomProxyMock.swift */; }; C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; }; C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */; }; C797C0B4CF45C66CD1921252 /* SoftLogoutScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC43313F21511C853D34544E /* SoftLogoutScreenViewModelTests.swift */; }; @@ -1386,6 +1385,7 @@ F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; }; F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */; }; F4D5A2A8304ED61621BF02D4 /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; }; + F4F29FF972C0C8B38757B2DD /* SpaceServiceRoomProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5416FE342A1E6A1B6D028999 /* SpaceServiceRoomProtocol.swift */; }; F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; }; F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; }; F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; }; @@ -1834,7 +1834,6 @@ 34ED3AB7E0287552A5648AB3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = ""; }; 353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConsentState.swift; sourceTree = ""; }; 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; - 355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxy.swift; sourceTree = ""; }; 35A057BA9BE0F079784CD061 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; @@ -1996,12 +1995,14 @@ 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModel.swift; sourceTree = ""; }; 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = ""; }; + 5416FE342A1E6A1B6D028999 /* SpaceServiceRoomProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceRoomProtocol.swift; sourceTree = ""; }; 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = ""; }; 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = ""; }; 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = ""; }; 54A7923F0115CF17ABC8047F /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/SAS.strings; sourceTree = ""; }; 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReactionsView.swift; sourceTree = ""; }; 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = ""; }; + 5530D3541C8832D858EB755A /* SpaceRoomInfoMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomInfoMock.swift; sourceTree = ""; }; 5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenViewModelTests.swift; sourceTree = ""; }; 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = ""; }; 55B3BF242C93CD32C4C3E08D /* ChatsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsFlowCoordinator.swift; sourceTree = ""; }; @@ -2393,7 +2394,6 @@ A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = ""; }; A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = ""; }; A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = ""; }; - A01F2E9FD8FF95AB89A345E6 /* SpaceRoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxyProtocol.swift; sourceTree = ""; }; A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = ""; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = ""; }; A07B011547B201A836C03052 /* EncryptionResetFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetFlowCoordinator.swift; sourceTree = ""; }; @@ -2480,7 +2480,6 @@ AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilderTests.swift; sourceTree = ""; }; AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = ""; }; AF2E6ADAE685F4109B1FE795 /* TimelineThreadSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineThreadSummaryView.swift; sourceTree = ""; }; - AF771312D208C8002A2F05C4 /* SpaceRoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxyMock.swift; sourceTree = ""; }; AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = ""; }; AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineView.swift; sourceTree = ""; }; AFEF489B8E2450E2BA1A314E /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SAS.strings; sourceTree = ""; }; @@ -2643,6 +2642,7 @@ CC666DAE98245269775329B2 /* RoomMembersFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersFlowCoordinatorTests.swift; sourceTree = ""; }; CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = ""; }; + CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceRoom.swift; sourceTree = ""; }; CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenViewModel.swift; sourceTree = ""; }; CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreen.swift; sourceTree = ""; }; CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -3640,8 +3640,8 @@ FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */, 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */, 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, + 5530D3541C8832D858EB755A /* SpaceRoomInfoMock.swift */, 7DB2A5FF1E68BA580A20D405 /* SpaceRoomListProxyMock.swift */, - AF771312D208C8002A2F05C4 /* SpaceRoomProxyMock.swift */, EF36FC3DE25B20B7FA91F1FD /* SpaceServiceProxyMock.swift */, B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */, 62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */, @@ -5703,10 +5703,10 @@ 75B3CE05643C7791D46AC54B /* LeaveSpaceHandleProxy.swift */, 4B2B564CA6570E1487A7C7CC /* SpaceRoomListProxy.swift */, EACD4855BDAD0799FD86B7B5 /* SpaceRoomListProxyProtocol.swift */, - 355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */, - A01F2E9FD8FF95AB89A345E6 /* SpaceRoomProxyProtocol.swift */, 226A56746AD99ABDA97189E1 /* SpaceServiceProxy.swift */, C57DB49B8426AA721BF85D83 /* SpaceServiceProxyProtocol.swift */, + CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */, + 5416FE342A1E6A1B6D028999 /* SpaceServiceRoomProtocol.swift */, ); path = Spaces; sourceTree = ""; @@ -8546,12 +8546,10 @@ F396470968764E2C3EDA92DA /* SpaceListScreenViewModel.swift in Sources */, 368EC173453FB805C677BFEF /* SpaceListScreenViewModelProtocol.swift in Sources */, 9B84F55288AB98783C11CC49 /* SpaceRoomCell.swift in Sources */, + 913BCABB99796F82E3D8D93D /* SpaceRoomInfoMock.swift in Sources */, 0DAB08C117E0391F3ADB2031 /* SpaceRoomListProxy.swift in Sources */, 9FBF0078657CA4F2A9747E98 /* SpaceRoomListProxyMock.swift in Sources */, 2EAA1B35D9CA24F090F48792 /* SpaceRoomListProxyProtocol.swift in Sources */, - 24D4E0BBC2ECD2AAD84E7159 /* SpaceRoomProxy.swift in Sources */, - C73CF79A578133D3AB7FB83D /* SpaceRoomProxyMock.swift in Sources */, - BE8075CA131C5EA3665C9E0D /* SpaceRoomProxyProtocol.swift in Sources */, 6CAADDC6318E41C7D7AA9526 /* SpaceScreen.swift in Sources */, EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */, 250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */, @@ -8560,6 +8558,8 @@ 94C2B531B96493B68B976E5F /* SpaceServiceProxy.swift in Sources */, A2091F4B1332D9BF273B09D5 /* SpaceServiceProxyMock.swift in Sources */, DB5200B87C4CE9DF0024AC4E /* SpaceServiceProxyProtocol.swift in Sources */, + 612196AF7826846A50C07FA6 /* SpaceServiceRoom.swift in Sources */, + F4F29FF972C0C8B38757B2DD /* SpaceServiceRoomProtocol.swift in Sources */, D0E257557DAC8A34C7B52A9F /* SpaceSettingsFlowCoordinator.swift in Sources */, 383063A7924F06D54BA9B24C /* SpaceSettingsScreen.swift in Sources */, 9DB4B303ECC05F0F33582594 /* SpacesAnnouncementSheetView.swift in Sources */, diff --git a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift index 3780d02fa..adb16c000 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceFlowCoordinator.swift @@ -18,12 +18,12 @@ enum SpaceFlowCoordinatorAction { enum SpaceFlowCoordinatorEntryPoint { case space(SpaceRoomListProxyProtocol) - case joinSpace(SpaceRoomProxyProtocol) + case joinSpace(SpaceServiceRoomProtocol) var spaceID: String { switch self { case .space(let spaceRoomListProxy): spaceRoomListProxy.id - case .joinSpace(let spaceRoomProxy): spaceRoomProxy.id + case .joinSpace(let spaceServiceRoom): spaceServiceRoom.id } } } @@ -294,8 +294,8 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { switch action { case .selectSpace(let spaceRoomListProxy): stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.space(spaceRoomListProxy)) - case .selectUnjoinedSpace(let spaceRoomProxy): - stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.joinSpace(spaceRoomProxy)) + case .selectUnjoinedSpace(let spaceServiceRoom): + stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.joinSpace(spaceServiceRoom)) case .selectRoom(let roomID): stateMachine.tryEvent(.startRoomFlow(roomID: roomID)) case .leftSpace: @@ -322,9 +322,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol { } private func presentJoinSpaceScreen() { - guard case let .joinSpace(spaceRoomProxy) = entryPoint else { fatalError("Attempting to join a space with the wrong entry point.") } + guard case let .joinSpace(spaceServiceRoom) = entryPoint else { fatalError("Attempting to join a space with the wrong entry point.") } - let parameters = JoinRoomScreenCoordinatorParameters(source: .space(spaceRoomProxy), + let parameters = JoinRoomScreenCoordinatorParameters(source: .space(spaceServiceRoom), userSession: flowParameters.userSession, userIndicatorController: flowParameters.userIndicatorController, appSettings: flowParameters.appSettings) diff --git a/ElementX/Sources/Mocks/ClientProxyMock.swift b/ElementX/Sources/Mocks/ClientProxyMock.swift index 7e537c63b..3188e02dc 100644 --- a/ElementX/Sources/Mocks/ClientProxyMock.swift +++ b/ElementX/Sources/Mocks/ClientProxyMock.swift @@ -123,8 +123,8 @@ extension ClientProxyMock { roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock()) return .joined(roomProxy) } - } else if let spaceRoomProxy = configuration.spaceServiceConfiguration.topLevelSpaces.first(where: { $0.id == identifier }) { - let roomProxy = await JoinedRoomProxyMock(.init(id: spaceRoomProxy.id, name: spaceRoomProxy.name, isSpace: spaceRoomProxy.isSpace)) + } else if let spaceServiceRoom = configuration.spaceServiceConfiguration.topLevelSpaces.first(where: { $0.id == identifier }) { + let roomProxy = await JoinedRoomProxyMock(.init(id: spaceServiceRoom.id, name: spaceServiceRoom.name, isSpace: spaceServiceRoom.isSpace)) roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock()) return .joined(roomProxy) } else { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 35257639a..1126cf84d 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -16721,16 +16721,16 @@ class SpaceRoomListProxyMock: SpaceRoomListProxyProtocol, @unchecked Sendable { set(value) { underlyingId = value } } var underlyingId: String! - var spaceRoomProxyPublisher: CurrentValuePublisher { - get { return underlyingSpaceRoomProxyPublisher } - set(value) { underlyingSpaceRoomProxyPublisher = value } + var spaceServiceRoomPublisher: CurrentValuePublisher { + get { return underlyingSpaceServiceRoomPublisher } + set(value) { underlyingSpaceServiceRoomPublisher = value } } - var underlyingSpaceRoomProxyPublisher: CurrentValuePublisher! - var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { + var underlyingSpaceServiceRoomPublisher: CurrentValuePublisher! + var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get { return underlyingSpaceRoomsPublisher } set(value) { underlyingSpaceRoomsPublisher = value } } - var underlyingSpaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never>! + var underlyingSpaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never>! var paginationStatePublisher: CurrentValuePublisher { get { return underlyingPaginationStatePublisher } set(value) { underlyingPaginationStatePublisher = value } @@ -16773,55 +16773,12 @@ class SpaceRoomListProxyMock: SpaceRoomListProxyProtocol, @unchecked Sendable { await paginateClosure?() } } -class SpaceRoomProxyMock: SpaceRoomProxyProtocol, @unchecked Sendable { - var id: String { - get { return underlyingId } - set(value) { underlyingId = value } - } - var underlyingId: String! - var name: String { - get { return underlyingName } - set(value) { underlyingName = value } - } - var underlyingName: String! - var rawName: String? - var avatarURL: URL? - var isSpace: Bool { - get { return underlyingIsSpace } - set(value) { underlyingIsSpace = value } - } - var underlyingIsSpace: Bool! - var isDirect: Bool? - var childrenCount: Int { - get { return underlyingChildrenCount } - set(value) { underlyingChildrenCount = value } - } - var underlyingChildrenCount: Int! - var joinedMembersCount: Int { - get { return underlyingJoinedMembersCount } - set(value) { underlyingJoinedMembersCount = value } - } - var underlyingJoinedMembersCount: Int! - var heroes: [UserProfileProxy] = [] - var topic: String? - var canonicalAlias: String? - var joinRule: JoinRule? - var worldReadable: Bool? - var guestCanJoin: Bool { - get { return underlyingGuestCanJoin } - set(value) { underlyingGuestCanJoin = value } - } - var underlyingGuestCanJoin: Bool! - var state: Membership? - var via: [String] = [] - -} class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { - var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { + var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get { return underlyingTopLevelSpacesPublisher } set(value) { underlyingTopLevelSpacesPublisher = value } } - var underlyingTopLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never>! + var underlyingTopLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never>! //MARK: - spaceRoomList @@ -16925,13 +16882,13 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { var spaceForIdentifierSpaceIDReceivedSpaceID: String? var spaceForIdentifierSpaceIDReceivedInvocations: [String] = [] - var spaceForIdentifierSpaceIDUnderlyingReturnValue: Result! - var spaceForIdentifierSpaceIDReturnValue: Result! { + var spaceForIdentifierSpaceIDUnderlyingReturnValue: Result! + var spaceForIdentifierSpaceIDReturnValue: Result! { get { if Thread.isMainThread { return spaceForIdentifierSpaceIDUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { returnValue = spaceForIdentifierSpaceIDUnderlyingReturnValue } @@ -16949,9 +16906,9 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } } } - var spaceForIdentifierSpaceIDClosure: ((String) async -> Result)? + var spaceForIdentifierSpaceIDClosure: ((String) async -> Result)? - func spaceForIdentifier(spaceID: String) async -> Result { + func spaceForIdentifier(spaceID: String) async -> Result { spaceForIdentifierSpaceIDCallsCount += 1 spaceForIdentifierSpaceIDReceivedSpaceID = spaceID DispatchQueue.main.async { @@ -17065,13 +17022,13 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { var joinedParentsChildIDReceivedChildID: String? var joinedParentsChildIDReceivedInvocations: [String] = [] - var joinedParentsChildIDUnderlyingReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! - var joinedParentsChildIDReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! { + var joinedParentsChildIDUnderlyingReturnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>! + var joinedParentsChildIDReturnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>! { get { if Thread.isMainThread { return joinedParentsChildIDUnderlyingReturnValue } else { - var returnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>? = nil + var returnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>? = nil DispatchQueue.main.sync { returnValue = joinedParentsChildIDUnderlyingReturnValue } @@ -17089,9 +17046,9 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } } } - var joinedParentsChildIDClosure: ((String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>)? + var joinedParentsChildIDClosure: ((String) async -> Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>)? - func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { + func joinedParents(childID: String) async -> Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError> { joinedParentsChildIDCallsCount += 1 joinedParentsChildIDReceivedChildID = childID DispatchQueue.main.async { @@ -17104,6 +17061,49 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } } } +class SpaceServiceRoomMock: SpaceServiceRoomProtocol, @unchecked Sendable { + var id: String { + get { return underlyingId } + set(value) { underlyingId = value } + } + var underlyingId: String! + var name: String { + get { return underlyingName } + set(value) { underlyingName = value } + } + var underlyingName: String! + var rawName: String? + var avatarURL: URL? + var isSpace: Bool { + get { return underlyingIsSpace } + set(value) { underlyingIsSpace = value } + } + var underlyingIsSpace: Bool! + var isDirect: Bool? + var childrenCount: Int { + get { return underlyingChildrenCount } + set(value) { underlyingChildrenCount = value } + } + var underlyingChildrenCount: Int! + var joinedMembersCount: Int { + get { return underlyingJoinedMembersCount } + set(value) { underlyingJoinedMembersCount = value } + } + var underlyingJoinedMembersCount: Int! + var heroes: [UserProfileProxy] = [] + var topic: String? + var canonicalAlias: String? + var joinRule: JoinRule? + var worldReadable: Bool? + var guestCanJoin: Bool { + get { return underlyingGuestCanJoin } + set(value) { underlyingGuestCanJoin = value } + } + var underlyingGuestCanJoin: Bool! + var state: Membership? + var via: [String] = [] + +} class StaticRoomSummaryProviderMock: StaticRoomSummaryProviderProtocol, @unchecked Sendable { var statePublisher: CurrentValuePublisher { get { return underlyingStatePublisher } diff --git a/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift b/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift index 3d9e324e7..c385196a9 100644 --- a/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift +++ b/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift @@ -98,17 +98,17 @@ extension RoomPreviewProxyMock { underlyingOwnMembershipDetails = roomMembershipDetails } - convenience init(spaceRoomProxy: SpaceRoomProxyProtocol) { - self.init(Configuration(roomID: spaceRoomProxy.id, - canonicalAlias: spaceRoomProxy.canonicalAlias ?? "", - name: spaceRoomProxy.name, - topic: spaceRoomProxy.topic ?? "", - avatarURL: spaceRoomProxy.avatarURL?.absoluteString ?? "", - numJoinedMembers: UInt64(spaceRoomProxy.joinedMembersCount), - numActiveMembers: UInt64(spaceRoomProxy.joinedMembersCount), - roomType: spaceRoomProxy.isSpace ? .space : .room, + convenience init(spaceServiceRoom: SpaceServiceRoomProtocol) { + self.init(Configuration(roomID: spaceServiceRoom.id, + canonicalAlias: spaceServiceRoom.canonicalAlias ?? "", + name: spaceServiceRoom.name, + topic: spaceServiceRoom.topic ?? "", + avatarURL: spaceServiceRoom.avatarURL?.absoluteString ?? "", + numJoinedMembers: UInt64(spaceServiceRoom.joinedMembersCount), + numActiveMembers: UInt64(spaceServiceRoom.joinedMembersCount), + roomType: spaceServiceRoom.isSpace ? .space : .room, membership: nil, - joinRule: spaceRoomProxy.joinRule ?? .restricted(rules: []), + joinRule: spaceServiceRoom.joinRule ?? .restricted(rules: []), isDirect: false)) } } diff --git a/ElementX/Sources/Mocks/SDK/LeaveSpaceHandleSDKMock.swift b/ElementX/Sources/Mocks/SDK/LeaveSpaceHandleSDKMock.swift index 83467510e..db4e11882 100644 --- a/ElementX/Sources/Mocks/SDK/LeaveSpaceHandleSDKMock.swift +++ b/ElementX/Sources/Mocks/SDK/LeaveSpaceHandleSDKMock.swift @@ -23,17 +23,17 @@ extension LeaveSpaceHandleSDKMock { } extension [LeaveSpaceRoom] { - static func mockRoomsWithSpace(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { - mockRooms + mockSingleSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: isLastAdmin) + static func mockRoomsWithSpace(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { + mockRooms + mockSingleSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: isLastAdmin) } - static func mockSingleSpace(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { - [LeaveSpaceRoom(spaceRoom: SpaceRoom(id: spaceRoomProxy.id, - name: spaceRoomProxy.name, - avatarURL: spaceRoomProxy.avatarURL, + static func mockSingleSpace(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { + [LeaveSpaceRoom(spaceRoom: SpaceRoom(id: spaceServiceRoom.id, + name: spaceServiceRoom.name, + avatarURL: spaceServiceRoom.avatarURL, isSpace: true, - memberCount: UInt64(spaceRoomProxy.joinedMembersCount), - joinRule: spaceRoomProxy.joinRule), + memberCount: UInt64(spaceServiceRoom.joinedMembersCount), + joinRule: spaceServiceRoom.joinRule), isLastAdmin: isLastAdmin)] } diff --git a/ElementX/Sources/Mocks/SpaceRoomInfoMock.swift b/ElementX/Sources/Mocks/SpaceRoomInfoMock.swift new file mode 100644 index 000000000..b1feb1955 --- /dev/null +++ b/ElementX/Sources/Mocks/SpaceRoomInfoMock.swift @@ -0,0 +1,205 @@ +// +// Copyright 2025 Element Creations Ltd. +// Copyright 2025 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +extension SpaceServiceRoomMock { + struct Configuration { + var id: String = UUID().uuidString + var name: String? + var rawName: String? + var avatarURL: URL? + + var isSpace: Bool + var isDirect: Bool? + var childrenCount = 0 + + var joinedMembersCount = 0 + var heroes: [UserProfileProxy] = [] + var topic: String? + var canonicalAlias: String? + + var joinRule: JoinRule? + var worldReadable: Bool? + var guestCanJoin = true + var state: Membership? + } + + convenience init(_ configuration: Configuration) { + self.init() + + id = configuration.id + name = configuration.name ?? configuration.id + rawName = configuration.rawName + avatarURL = configuration.avatarURL + isSpace = configuration.isSpace + isDirect = configuration.isDirect + childrenCount = configuration.childrenCount + joinedMembersCount = configuration.joinedMembersCount + heroes = configuration.heroes + topic = configuration.topic + canonicalAlias = configuration.canonicalAlias + joinRule = configuration.joinRule + worldReadable = configuration.worldReadable + guestCanJoin = configuration.guestCanJoin + state = configuration.state + } +} + +extension [SpaceServiceRoomProtocol] { + static var mockJoinedSpaces: [SpaceServiceRoomMock] { + [ + SpaceServiceRoomMock(.init(id: "space1", + name: "The Foundation", + isSpace: true, + childrenCount: 1, + joinedMembersCount: 500, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space2", + name: "The Second Foundation", + isSpace: true, + childrenCount: 1, + joinedMembersCount: 100, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space3", + name: "The Galactic Empire", + isSpace: true, + childrenCount: 25000, + joinedMembersCount: 1_000_000_000, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space4", + name: "The Korellians", + isSpace: true, + childrenCount: 27, + joinedMembersCount: 2_000_000, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space5", + name: "The Luminists", + isSpace: true, + childrenCount: 1, + joinedMembersCount: 100_000, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space6", + name: "The Anacreons", + isSpace: true, + childrenCount: 25, + joinedMembersCount: 400_000, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space7", + name: "The Thespians", + isSpace: true, + childrenCount: 15, + joinedMembersCount: 300_000, + state: .joined)) + ] + } + + static var mockJoinedSpaces2: [SpaceServiceRoomMock] { + [ + SpaceServiceRoomMock(.init(id: "space1", + name: "The Foundation", + avatarURL: .mockMXCAvatar, + isSpace: true, + childrenCount: 1, + joinedMembersCount: 500, + canonicalAlias: "#the-foundation:matrix.org", + state: .joined)), + SpaceServiceRoomMock(.init(id: "space2", + name: "The Second Foundation", + isSpace: true, + childrenCount: 1, + joinedMembersCount: 100, + state: .joined)), + SpaceServiceRoomMock(.init(id: "space3", + name: "The Galactic Empire", + isSpace: true, + childrenCount: 25000, + joinedMembersCount: 1_000_000_000, + canonicalAlias: "#the-galactic-empire:matrix.org", + state: .joined)) + ] + } + + static var mockSpaceList: [SpaceServiceRoomProtocol] { + makeSpaceRooms(isSpace: true) + makeSpaceRooms(isSpace: false) + } + + static var mockSingleRoom: [SpaceServiceRoomProtocol] { + [SpaceServiceRoomMock(.init(id: "!spaceroom:matrix.org", + name: "Management", + isSpace: false, + joinedMembersCount: 12, + topic: "This is where everything gets organised 📋.", + state: .joined))] + } + + private static func makeSpaceRooms(isSpace: Bool) -> [SpaceServiceRoomMock] { + let typeName = isSpace ? "Space" : "Room" + + return [ + SpaceServiceRoomMock(.init(id: "!\(typeName.lowercased())1:matrix.org", + name: "Company \(typeName)", + isSpace: isSpace)), + SpaceServiceRoomMock(.init(id: "!\(typeName.lowercased())2:matrix.org", + name: "Public \(typeName)", + avatarURL: .mockMXCAvatar, + isSpace: isSpace, + joinedMembersCount: 78, + topic: "Discussion on specific topic goes here.", + joinRule: .public)), + SpaceServiceRoomMock(.init(id: "!\(typeName.lowercased())3:matrix.org", + name: "Joined \(typeName)", + isSpace: isSpace, + joinedMembersCount: 123, + topic: "Discussion on specific topic goes here.", + joinRule: .restricted(rules: []), + state: .joined)) + ] + } +} + +extension SpaceServiceRoomMock { + convenience init(mode: JoinRoomScreenMode) { + var state: Membership? + var joinRule: JoinRule? + + switch mode { + case .joinable: + joinRule = .public + case .restricted: + joinRule = .restricted(rules: []) + case .inviteRequired: + joinRule = .private + case .invited: + state = .invited + joinRule = .private + case .knockable: + joinRule = .knock + case .knocked: + state = .knocked + joinRule = .knock + case .banned: + state = .banned + case .loading, .unknown, .forbidden: + break + } + + self.init(.init(id: "1", + name: "The Three-Body Problem", + avatarURL: .mockMXCAvatar, + isSpace: true, + childrenCount: 100, + joinedMembersCount: 123, + heroes: [.mockAlice, .mockBob, .mockCharlie], + topic: "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”", + canonicalAlias: "#3-body-problem:matrix.org", + joinRule: joinRule, + state: state)) + } +} diff --git a/ElementX/Sources/Mocks/SpaceRoomListProxyMock.swift b/ElementX/Sources/Mocks/SpaceRoomListProxyMock.swift index a561c2d5d..7174cf2be 100644 --- a/ElementX/Sources/Mocks/SpaceRoomListProxyMock.swift +++ b/ElementX/Sources/Mocks/SpaceRoomListProxyMock.swift @@ -12,16 +12,16 @@ import MatrixRustSDK extension SpaceRoomListProxyMock { class Configuration { - var spaceRoomProxy: SpaceRoomProxyProtocol - var initialSpaceRooms: [SpaceRoomProxyProtocol] + var spaceServiceRoom: SpaceServiceRoomProtocol + var initialSpaceRooms: [SpaceServiceRoomProtocol] var paginationStateSubject: CurrentValueSubject - var paginationResponses: [[SpaceRoomProxyProtocol]] + var paginationResponses: [[SpaceServiceRoomProtocol]] - init(spaceRoomProxy: SpaceRoomProxyProtocol, - initialSpaceRooms: [SpaceRoomProxyProtocol] = [], + init(spaceServiceRoom: SpaceServiceRoomProtocol, + initialSpaceRooms: [SpaceServiceRoomProtocol] = [], paginationStateSubject: CurrentValueSubject = .init(.idle(endReached: true)), - paginationResponses: [[SpaceRoomProxyProtocol]] = []) { - self.spaceRoomProxy = spaceRoomProxy + paginationResponses: [[SpaceServiceRoomProtocol]] = []) { + self.spaceServiceRoom = spaceServiceRoom self.initialSpaceRooms = initialSpaceRooms self.paginationStateSubject = paginationStateSubject self.paginationResponses = paginationResponses @@ -31,10 +31,10 @@ extension SpaceRoomListProxyMock { convenience init(_ configuration: Configuration) { self.init() - let spaceRoomsSubject: CurrentValueSubject<[SpaceRoomProxyProtocol], Never> = .init(configuration.initialSpaceRooms) + let spaceRoomsSubject: CurrentValueSubject<[SpaceServiceRoomProtocol], Never> = .init(configuration.initialSpaceRooms) - id = configuration.spaceRoomProxy.id - spaceRoomProxyPublisher = .init(configuration.spaceRoomProxy) + id = configuration.spaceServiceRoom.id + spaceServiceRoomPublisher = .init(configuration.spaceServiceRoom) spaceRoomsPublisher = spaceRoomsSubject.asCurrentValuePublisher() paginationStatePublisher = configuration.paginationStateSubject.asCurrentValuePublisher() diff --git a/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift b/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift deleted file mode 100644 index c85aa7017..000000000 --- a/ElementX/Sources/Mocks/SpaceRoomProxyMock.swift +++ /dev/null @@ -1,205 +0,0 @@ -// -// Copyright 2025 Element Creations Ltd. -// Copyright 2025 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import MatrixRustSDK - -extension SpaceRoomProxyMock { - struct Configuration { - var id: String = UUID().uuidString - var name: String? - var rawName: String? - var avatarURL: URL? - - var isSpace: Bool - var isDirect: Bool? - var childrenCount = 0 - - var joinedMembersCount = 0 - var heroes: [UserProfileProxy] = [] - var topic: String? - var canonicalAlias: String? - - var joinRule: JoinRule? - var worldReadable: Bool? - var guestCanJoin = true - var state: Membership? - } - - convenience init(_ configuration: Configuration) { - self.init() - - id = configuration.id - name = configuration.name ?? configuration.id - rawName = configuration.rawName - avatarURL = configuration.avatarURL - isSpace = configuration.isSpace - isDirect = configuration.isDirect - childrenCount = configuration.childrenCount - joinedMembersCount = configuration.joinedMembersCount - heroes = configuration.heroes - topic = configuration.topic - canonicalAlias = configuration.canonicalAlias - joinRule = configuration.joinRule - worldReadable = configuration.worldReadable - guestCanJoin = configuration.guestCanJoin - state = configuration.state - } -} - -extension [SpaceRoomProxyProtocol] { - static var mockJoinedSpaces: [SpaceRoomProxyMock] { - [ - SpaceRoomProxyMock(.init(id: "space1", - name: "The Foundation", - isSpace: true, - childrenCount: 1, - joinedMembersCount: 500, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space2", - name: "The Second Foundation", - isSpace: true, - childrenCount: 1, - joinedMembersCount: 100, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space3", - name: "The Galactic Empire", - isSpace: true, - childrenCount: 25000, - joinedMembersCount: 1_000_000_000, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space4", - name: "The Korellians", - isSpace: true, - childrenCount: 27, - joinedMembersCount: 2_000_000, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space5", - name: "The Luminists", - isSpace: true, - childrenCount: 1, - joinedMembersCount: 100_000, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space6", - name: "The Anacreons", - isSpace: true, - childrenCount: 25, - joinedMembersCount: 400_000, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space7", - name: "The Thespians", - isSpace: true, - childrenCount: 15, - joinedMembersCount: 300_000, - state: .joined)) - ] - } - - static var mockJoinedSpaces2: [SpaceRoomProxyMock] { - [ - SpaceRoomProxyMock(.init(id: "space1", - name: "The Foundation", - avatarURL: .mockMXCAvatar, - isSpace: true, - childrenCount: 1, - joinedMembersCount: 500, - canonicalAlias: "#the-foundation:matrix.org", - state: .joined)), - SpaceRoomProxyMock(.init(id: "space2", - name: "The Second Foundation", - isSpace: true, - childrenCount: 1, - joinedMembersCount: 100, - state: .joined)), - SpaceRoomProxyMock(.init(id: "space3", - name: "The Galactic Empire", - isSpace: true, - childrenCount: 25000, - joinedMembersCount: 1_000_000_000, - canonicalAlias: "#the-galactic-empire:matrix.org", - state: .joined)) - ] - } - - static var mockSpaceList: [SpaceRoomProxyProtocol] { - makeSpaceRooms(isSpace: true) + makeSpaceRooms(isSpace: false) - } - - static var mockSingleRoom: [SpaceRoomProxyProtocol] { - [SpaceRoomProxyMock(.init(id: "!spaceroom:matrix.org", - name: "Management", - isSpace: false, - joinedMembersCount: 12, - topic: "This is where everything gets organised 📋.", - state: .joined))] - } - - private static func makeSpaceRooms(isSpace: Bool) -> [SpaceRoomProxyMock] { - let typeName = isSpace ? "Space" : "Room" - - return [ - SpaceRoomProxyMock(.init(id: "!\(typeName.lowercased())1:matrix.org", - name: "Company \(typeName)", - isSpace: isSpace)), - SpaceRoomProxyMock(.init(id: "!\(typeName.lowercased())2:matrix.org", - name: "Public \(typeName)", - avatarURL: .mockMXCAvatar, - isSpace: isSpace, - joinedMembersCount: 78, - topic: "Discussion on specific topic goes here.", - joinRule: .public)), - SpaceRoomProxyMock(.init(id: "!\(typeName.lowercased())3:matrix.org", - name: "Joined \(typeName)", - isSpace: isSpace, - joinedMembersCount: 123, - topic: "Discussion on specific topic goes here.", - joinRule: .restricted(rules: []), - state: .joined)) - ] - } -} - -extension SpaceRoomProxyMock { - convenience init(mode: JoinRoomScreenMode) { - var state: Membership? - var joinRule: JoinRule? - - switch mode { - case .joinable: - joinRule = .public - case .restricted: - joinRule = .restricted(rules: []) - case .inviteRequired: - joinRule = .private - case .invited: - state = .invited - joinRule = .private - case .knockable: - joinRule = .knock - case .knocked: - state = .knocked - joinRule = .knock - case .banned: - state = .banned - case .loading, .unknown, .forbidden: - break - } - - self.init(.init(id: "1", - name: "The Three-Body Problem", - avatarURL: .mockMXCAvatar, - isSpace: true, - childrenCount: 100, - joinedMembersCount: 123, - heroes: [.mockAlice, .mockBob, .mockCharlie], - topic: "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”", - canonicalAlias: "#3-body-problem:matrix.org", - joinRule: joinRule, - state: state)) - } -} diff --git a/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift b/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift index 7a7c48bbb..715d3b4d3 100644 --- a/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift +++ b/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift @@ -13,8 +13,8 @@ import MatrixRustSDKMocks extension SpaceServiceProxyMock { struct Configuration { - var topLevelSpaces: [SpaceRoomProxyProtocol] = [] - var joinedParentSpaces: [SpaceRoomProxyProtocol] = [] + var topLevelSpaces: [SpaceServiceRoomProtocol] = [] + var joinedParentSpaces: [SpaceServiceRoomProtocol] = [] var spaceRoomLists: [String: SpaceRoomListProxyMock] = [:] var leaveSpaceRooms: [LeaveSpaceRoom] = [] } @@ -43,11 +43,11 @@ extension SpaceServiceProxyMock { extension SpaceServiceProxyMock.Configuration { static var populated: SpaceServiceProxyMock.Configuration { - let spaceRoomLists = [SpaceRoomProxyProtocol].mockJoinedSpaces.map { - ($0.id, SpaceRoomListProxyMock(.init(spaceRoomProxy: $0, initialSpaceRooms: .mockSpaceList))) + let spaceRoomLists = [SpaceServiceRoomProtocol].mockJoinedSpaces.map { + ($0.id, SpaceRoomListProxyMock(.init(spaceServiceRoom: $0, initialSpaceRooms: .mockSpaceList))) } - let subSpaceRoomLists = [SpaceRoomProxyProtocol].mockSpaceList.map { - ($0.id, SpaceRoomListProxyMock(.init(spaceRoomProxy: $0, initialSpaceRooms: .mockSingleRoom))) + let subSpaceRoomLists = [SpaceServiceRoomProtocol].mockSpaceList.map { + ($0.id, SpaceRoomListProxyMock(.init(spaceServiceRoom: $0, initialSpaceRooms: .mockSingleRoom))) } return .init(topLevelSpaces: .mockJoinedSpaces, spaceRoomLists: .init(uniqueKeysWithValues: spaceRoomLists + subSpaceRoomLists)) diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift index f920a9eaf..5140dacb1 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift @@ -18,14 +18,14 @@ struct JoinRoomScreenCoordinatorParameters { enum JoinRoomScreenSource { case generic(roomID: String, via: [String]) - case space(SpaceRoomProxyProtocol) + case space(SpaceServiceRoomProtocol) func roomIDAndVia() -> (roomID: String, via: [String]) { switch self { case let .generic(roomID: roomID, via: via): return (roomID: roomID, via: via) - case let .space(spaceRoomProxy): - return (roomID: spaceRoomProxy.id, via: spaceRoomProxy.via) + case let .space(spaceServiceRoom): + return (roomID: spaceServiceRoom.id, via: spaceServiceRoom.via) } } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift index 729026982..2d24a81e2 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift @@ -49,7 +49,7 @@ struct JoinRoomScreenRoomDetails { let isSpace: Bool? let childrenCount: Int? - let spaceVisibility: SpaceRoomProxyVisibility? + let spaceVisibility: SpaceServiceRoomVisibility? } struct JoinRoomScreenViewState: BindableState { diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index c91af28ca..8e08f7e47 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -172,8 +172,8 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo switch source { case .generic(let roomID, _): await updateGenericRoomDetails(roomID: roomID, roomInfo: roomInfo, inviter: inviter) - case .space(let spaceRoomProxy): - await updateSpaceRoomDetails(spaceRoomProxy: spaceRoomProxy, inviter: inviter) + case .space(let spaceServiceRoom): + await updateSpaceRoomDetails(spaceServiceRoom: spaceServiceRoom, inviter: inviter) } await updateMode() } @@ -200,18 +200,18 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo spaceVisibility: nil) } - private func updateSpaceRoomDetails(spaceRoomProxy: SpaceRoomProxyProtocol, inviter: RoomInviterDetails?) async { - state.roomDetails = JoinRoomScreenRoomDetails(name: spaceRoomProxy.name, - topic: spaceRoomProxy.topic, - canonicalAlias: spaceRoomProxy.canonicalAlias, - avatar: spaceRoomProxy.avatar, - memberCount: spaceRoomProxy.joinedMembersCount, - heroes: spaceRoomProxy.heroes, + private func updateSpaceRoomDetails(spaceServiceRoom: SpaceServiceRoomProtocol, inviter: RoomInviterDetails?) async { + state.roomDetails = JoinRoomScreenRoomDetails(name: spaceServiceRoom.name, + topic: spaceServiceRoom.topic, + canonicalAlias: spaceServiceRoom.canonicalAlias, + avatar: spaceServiceRoom.avatar, + memberCount: spaceServiceRoom.joinedMembersCount, + heroes: spaceServiceRoom.heroes, inviter: inviter, - isDirect: spaceRoomProxy.isDirect, - isSpace: spaceRoomProxy.isSpace, - childrenCount: spaceRoomProxy.childrenCount, - spaceVisibility: spaceRoomProxy.visibility) + isDirect: spaceServiceRoom.isDirect, + isSpace: spaceServiceRoom.isSpace, + childrenCount: spaceServiceRoom.childrenCount, + spaceVisibility: spaceServiceRoom.visibility) } private func updateMode() async { @@ -225,16 +225,16 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo return } - if case .space(let spaceRoomProxy) = source { - switch spaceRoomProxy.state { + if case .space(let spaceServiceRoom) = source { + switch spaceServiceRoom.state { case .invited: - state.mode = .invited(isDM: spaceRoomProxy.isDirect == true && spaceRoomProxy.joinedMembersCount == 1) + state.mode = .invited(isDM: spaceServiceRoom.isDirect == true && spaceServiceRoom.joinedMembersCount == 1) case .knocked: state.mode = .knocked case .banned: state.mode = .banned(sender: nil, reason: nil) default: - switch spaceRoomProxy.joinRule { + switch spaceServiceRoom.joinRule { case .private, .invite: state.mode = .inviteRequired case .knock, .knockRestricted: diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index ea99afbd0..c8b688386 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -445,7 +445,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable { } let source: JoinRoomScreenSource = if isSpace { - .space(SpaceRoomProxyMock(mode: mode)) + .space(SpaceServiceRoomMock(mode: mode)) } else { .generic(roomID: "1", via: []) } diff --git a/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/ManageAuthorizedSpacesScreenModels.swift b/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/ManageAuthorizedSpacesScreenModels.swift index 6142ee892..0b9c2ab3f 100644 --- a/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/ManageAuthorizedSpacesScreenModels.swift +++ b/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/ManageAuthorizedSpacesScreenModels.swift @@ -37,7 +37,7 @@ enum ManageAuthorizedSpacesScreenViewAction { } struct AuthorizedSpacesSelection { - let joinedSpaces: [SpaceRoomProxyProtocol] + let joinedSpaces: [SpaceServiceRoomProtocol] let unknownSpacesIDs: [String] let initialSelectedIDs: Set let selectedIDs: PassthroughSubject, Never> = .init() diff --git a/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/View/ManageAuthorizedSpacesScreen.swift b/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/View/ManageAuthorizedSpacesScreen.swift index 36ecd6761..7f3d10b0a 100644 --- a/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/View/ManageAuthorizedSpacesScreen.swift +++ b/ElementX/Sources/Screens/ManageAuthorizedSpacesScreen/View/ManageAuthorizedSpacesScreen.swift @@ -77,7 +77,7 @@ struct ManageAuthorizedSpacesScreen: View { } } - private func avatar(space: SpaceRoomProxyProtocol) -> some View { + private func avatar(space: SpaceServiceRoomProtocol) -> some View { RoomAvatarImage(avatar: space.avatar, avatarSize: .room(on: .authorizedSpaces), mediaProvider: context.mediaProvider) diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift index df3ada8ca..e591b2162 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift @@ -32,7 +32,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState { var canEditHistoryVisibility = false /// The union of joined parent spaces and the joined spaces in the current access type - var selectableJoinedSpaces: [SpaceRoomProxyProtocol] = [] + var selectableJoinedSpaces: [SpaceServiceRoomProtocol] = [] /// The count of the intersection between the set of joined parent spaces and the set of spaces in the current access type var selectableSpacesCount: Int { @@ -118,7 +118,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState { enum SpaceSelection { /// There is only one available parent space for selection and is joined by the user - case singleJoined(SpaceRoomProxyProtocol) + case singleJoined(SpaceServiceRoomProtocol) /// There is only one available space for selection and is unknown to the user case singleUnknown(id: String) /// Multiple spaces are available for selection diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift index 44a175dd0..c7f1599df 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift @@ -305,7 +305,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, } private func setupSelectableJoinedSpaces() async { - var joinedParentSpaces: [SpaceRoomProxyProtocol] = [] + var joinedParentSpaces: [SpaceServiceRoomProtocol] = [] switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) { case .success(let value): joinedParentSpaces = value @@ -313,7 +313,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, break } - var nonParentJoinedSpaces: [SpaceRoomProxyProtocol] = [] + var nonParentJoinedSpaces: [SpaceServiceRoomProtocol] = [] for spaceID in state.currentSettings.accessType.spaceIDs where !joinedParentSpaces.contains(where: { $0.id == spaceID }) { if case let .success(.some(space)) = await clientProxy.spaceService.spaceForIdentifier(spaceID: spaceID) { nonParentJoinedSpaces.append(space) diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift index a1883016d..94119f01d 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift @@ -269,7 +269,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { AppSettings.resetAllSettings() let appSettings = AppSettings() appSettings.spaceSettingsEnabled = true - let space = [SpaceRoomProxyProtocol].mockSingleRoom[0] + let space = [SpaceServiceRoomProtocol].mockSingleRoom[0] return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", @@ -286,7 +286,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { AppSettings.resetAllSettings() let appSettings = AppSettings() appSettings.spaceSettingsEnabled = true - let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces + let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", @@ -319,7 +319,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { let appSettings = AppSettings() appSettings.spaceSettingsEnabled = true appSettings.knockingEnabled = true - let space = [SpaceRoomProxyProtocol].mockSingleRoom[0] + let space = [SpaceServiceRoomProtocol].mockSingleRoom[0] return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", @@ -337,7 +337,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { let appSettings = AppSettings() appSettings.spaceSettingsEnabled = true appSettings.knockingEnabled = true - let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces + let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", diff --git a/ElementX/Sources/Screens/Spaces/Common/SpaceHeaderView.swift b/ElementX/Sources/Screens/Spaces/Common/SpaceHeaderView.swift index e56a13b91..32a5e239b 100644 --- a/ElementX/Sources/Screens/Spaces/Common/SpaceHeaderView.swift +++ b/ElementX/Sources/Screens/Spaces/Common/SpaceHeaderView.swift @@ -10,36 +10,36 @@ import Compound import SwiftUI struct SpaceHeaderView: View { - let spaceRoomProxy: SpaceRoomProxyProtocol + let spaceServiceRoom: SpaceServiceRoomProtocol let mediaProvider: MediaProviderProtocol? @State private var isPresentingTopic = false var body: some View { VStack(spacing: 16) { - RoomAvatarImage(avatar: spaceRoomProxy.avatar, + RoomAvatarImage(avatar: spaceServiceRoom.avatar, avatarSize: .room(on: .spaceHeader), mediaProvider: mediaProvider) .accessibilityHidden(true) VStack(spacing: 8) { - Text(spaceRoomProxy.name) + Text(spaceServiceRoom.name) .font(.compound.headingLGBold) .foregroundStyle(.compound.textPrimary) .multilineTextAlignment(.center) - if let alias = spaceRoomProxy.canonicalAlias { + if let alias = spaceServiceRoom.canonicalAlias { CopyTextButton(content: alias) } spaceDetails - JoinedMembersBadgeView(heroes: spaceRoomProxy.heroes, - joinedCount: spaceRoomProxy.joinedMembersCount, + JoinedMembersBadgeView(heroes: spaceServiceRoom.heroes, + joinedCount: spaceServiceRoom.joinedMembersCount, mediaProvider: mediaProvider) } - if let topic = spaceRoomProxy.topic { + if let topic = spaceServiceRoom.topic { Button { isPresentingTopic = true } label: { Text(topic) .font(.compound.bodyMD) @@ -60,7 +60,7 @@ struct SpaceHeaderView: View { .frame(height: 1 / UIScreen.main.scale) } .sheet(isPresented: $isPresentingTopic) { - if let topic = spaceRoomProxy.topic { + if let topic = spaceServiceRoom.topic { SpaceHeaderTopicSheetView(topic: topic) } } @@ -79,7 +79,7 @@ struct SpaceHeaderView: View { } private var spaceDetailsVisibilityTitle: String { - switch spaceRoomProxy.visibility { + switch spaceServiceRoom.visibility { case .public: L10n.commonPublicSpace case .private: L10n.commonPrivateSpace case .restricted: L10n.commonSharedSpace @@ -88,7 +88,7 @@ struct SpaceHeaderView: View { } private var spaceDetailsVisibilityIcon: KeyPath { - switch spaceRoomProxy.visibility { + switch spaceServiceRoom.visibility { case .public: \.public case .private: \.lock case .restricted: \.space @@ -107,41 +107,41 @@ struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(spacing: 0) { ForEach(spaces, id: \.id) { space in - SpaceHeaderView(spaceRoomProxy: space, mediaProvider: mediaProvider) + SpaceHeaderView(spaceServiceRoom: space, mediaProvider: mediaProvider) } } } - static func makeSpaceRooms() -> [SpaceRoomProxyMock] { + static func makeSpaceRooms() -> [SpaceServiceRoomMock] { [ - SpaceRoomProxyMock(.init(id: "!space1:matrix.org", - name: "Company Space", - isSpace: true, - childrenCount: 10, - joinedMembersCount: 50)), - SpaceRoomProxyMock(.init(id: "!space2:matrix.org", - name: "Community Space", - avatarURL: .mockMXCAvatar, - isSpace: true, - childrenCount: 20, - joinedMembersCount: 78, - topic: "Description of the space goes right here.", - canonicalAlias: "#space:matrix.org", - joinRule: .public)), - SpaceRoomProxyMock(.init(id: "!space3:matrix.org", - name: "Subspace", - isSpace: true, - childrenCount: 30, - joinedMembersCount: 123, - heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], - topic: ["Description of the space goes right here.", - "Lorem ipsum dolor sit amet consectetur.", - "Leo viverra morbi habitant in.", - "Sem amet enim habitant nibh augue mauris.", - "Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.", - "Diam amet sit fermentum vulputate faucibus."].joined(separator: " "), - canonicalAlias: "#subspace:matrix.org", - joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) + SpaceServiceRoomMock(.init(id: "!space1:matrix.org", + name: "Company Space", + isSpace: true, + childrenCount: 10, + joinedMembersCount: 50)), + SpaceServiceRoomMock(.init(id: "!space2:matrix.org", + name: "Community Space", + avatarURL: .mockMXCAvatar, + isSpace: true, + childrenCount: 20, + joinedMembersCount: 78, + topic: "Description of the space goes right here.", + canonicalAlias: "#space:matrix.org", + joinRule: .public)), + SpaceServiceRoomMock(.init(id: "!space3:matrix.org", + name: "Subspace", + isSpace: true, + childrenCount: 30, + joinedMembersCount: 123, + heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], + topic: ["Description of the space goes right here.", + "Lorem ipsum dolor sit amet consectetur.", + "Leo viverra morbi habitant in.", + "Sem amet enim habitant nibh augue mauris.", + "Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.", + "Diam amet sit fermentum vulputate faucibus."].joined(separator: " "), + canonicalAlias: "#subspace:matrix.org", + joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) ] } } diff --git a/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift b/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift index db14d653c..e46326ed9 100644 --- a/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift +++ b/ElementX/Sources/Screens/Spaces/Common/SpaceRoomCell.swift @@ -13,32 +13,32 @@ import SwiftUI struct SpaceRoomCell: View { @Environment(\.dynamicTypeSize) var dynamicTypeSize - let spaceRoomProxy: SpaceRoomProxyProtocol + let spaceServiceRoom: SpaceServiceRoomProtocol let isSelected: Bool var isJoining = false let mediaProvider: MediaProviderProtocol! - enum Action { case select(SpaceRoomProxyProtocol), join(SpaceRoomProxyProtocol) } + enum Action { case select(SpaceServiceRoomProtocol), join(SpaceServiceRoomProtocol) } let action: (Action) -> Void private let verticalInsets = 12.0 private let horizontalInsets = 16.0 private var subtitle: String { - if spaceRoomProxy.isSpace { - switch spaceRoomProxy.visibility { + if spaceServiceRoom.isSpace { + switch spaceServiceRoom.visibility { case .public: L10n.commonPublicSpace case .private: L10n.commonPrivateSpace case .restricted: L10n.commonSharedSpace case .none: L10n.commonPrivateSpace } } else { - L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount) + L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount) } } var visibilityIcon: KeyPath? { - switch spaceRoomProxy.visibility { + switch spaceServiceRoom.visibility { case .public: \.public case .private: \.lockSolid case .restricted: nil @@ -47,16 +47,16 @@ struct SpaceRoomCell: View { } private var details: String { - if spaceRoomProxy.isSpace { - L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount) + if spaceServiceRoom.isSpace { + L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount) } else { - spaceRoomProxy.topic ?? " " // Use a single space to reserve a consistent amount of space. + spaceServiceRoom.topic ?? " " // Use a single space to reserve a consistent amount of space. } } var body: some View { Button { - action(.select(spaceRoomProxy)) + action(.select(spaceServiceRoom)) } label: { HStack(spacing: 16.0) { avatar @@ -74,13 +74,13 @@ struct SpaceRoomCell: View { .accessibilityElement(children: .combine) } .buttonStyle(SpaceRoomCellButtonStyle(isSelected: isSelected)) - .accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceRoomProxy.name)) + .accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceServiceRoom.name)) } @ViewBuilder @MainActor private var avatar: some View { if dynamicTypeSize < .accessibility3 { - RoomAvatarImage(avatar: spaceRoomProxy.avatar, + RoomAvatarImage(avatar: spaceServiceRoom.avatar, avatarSize: .room(on: .spaces), mediaProvider: mediaProvider) .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) @@ -91,7 +91,7 @@ struct SpaceRoomCell: View { private var content: some View { HStack(spacing: 16) { VStack(alignment: .leading, spacing: 2) { - Text(spaceRoomProxy.name) + Text(spaceServiceRoom.name) .font(.compound.bodyLGSemibold) .foregroundColor(.compound.textPrimary) .lineLimit(1) @@ -128,9 +128,9 @@ struct SpaceRoomCell: View { @ViewBuilder private var accessory: some View { - switch spaceRoomProxy.state { + switch spaceServiceRoom.state { case .none, .left, .invited: - Button(L10n.actionJoin) { action(.join(spaceRoomProxy)) } + Button(L10n.actionJoin) { action(.join(spaceServiceRoom)) } .font(.compound.bodyLG) .foregroundStyle(.compound.textActionAccent) .opacity(isJoining ? 0 : 1) @@ -159,21 +159,21 @@ struct SpaceRoomCellButtonStyle: ButtonStyle { struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview { static let mediaProvider = MediaProviderMock(configuration: .init()) - static let spaces = [SpaceRoomProxyProtocol].mockSpaceList + static let spaces = [SpaceServiceRoomProtocol].mockSpaceList static var previews: some View { VStack(spacing: 0) { ForEach(spaces, id: \.id) { space in - SpaceRoomCell(spaceRoomProxy: space, + SpaceRoomCell(spaceServiceRoom: space, isSelected: false, mediaProvider: mediaProvider) { _ in } } - SpaceRoomCell(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "Space being joined", isSpace: true)), + SpaceRoomCell(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "Space being joined", isSpace: true)), isSelected: false, isJoining: true, mediaProvider: mediaProvider) { _ in } - SpaceRoomCell(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "Room being joined", isSpace: false)), + SpaceRoomCell(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "Room being joined", isSpace: false)), isSelected: false, isJoining: true, mediaProvider: mediaProvider) { _ in } diff --git a/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceRoomDetailsCell.swift b/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceRoomDetailsCell.swift index 41eada0e7..5a55e9748 100644 --- a/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceRoomDetailsCell.swift +++ b/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceRoomDetailsCell.swift @@ -19,13 +19,13 @@ struct LeaveSpaceRoomDetailsCell: View { let action: () -> Void private var subtitle: String? { - guard !room.spaceRoomProxy.isSpace else { return nil } - let memberCount = L10n.commonMemberCount(room.spaceRoomProxy.joinedMembersCount) + guard !room.spaceServiceRoom.isSpace else { return nil } + let memberCount = L10n.commonMemberCount(room.spaceServiceRoom.joinedMembersCount) return room.isLastAdmin ? L10n.screenLeaveSpaceLastAdminInfo(memberCount) : memberCount } var visibilityIcon: KeyPath? { - switch room.spaceRoomProxy.visibility { + switch room.spaceServiceRoom.visibility { case .public: \.public case .private: \.lockSolid case .restricted: nil @@ -37,13 +37,13 @@ struct LeaveSpaceRoomDetailsCell: View { Button(action: action) { HStack(spacing: 16) { if dynamicTypeSize < .accessibility3 { - RoomAvatarImage(avatar: room.spaceRoomProxy.avatar, + RoomAvatarImage(avatar: room.spaceServiceRoom.avatar, avatarSize: .room(on: .leaveSpace), mediaProvider: mediaProvider) } VStack(alignment: .leading, spacing: 0) { - Text(room.spaceRoomProxy.name) + Text(room.spaceServiceRoom.name) .font(.compound.bodyLGSemibold) .foregroundStyle(.compound.textPrimary) .lineLimit(1) @@ -91,40 +91,40 @@ struct LeaveSpaceRoomDetailsCell: View { struct LeaveSpaceRoomDetailsCell_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(spacing: 0) { - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "1", - name: "Space", - isSpace: true)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "1", + name: "Space", + isSpace: true)), isLastAdmin: false, isSelected: true), mediaProvider: MediaProviderMock(configuration: .init())) { } - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2", - name: "My Space", - isSpace: true)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2", + name: "My Space", + isSpace: true)), isLastAdmin: true, isSelected: false), mediaProvider: MediaProviderMock(configuration: .init())) { } - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2", - name: "My Space", - isSpace: true)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2", + name: "My Space", + isSpace: true)), isLastAdmin: true, isSelected: false), hideSelection: true, mediaProvider: MediaProviderMock(configuration: .init())) { } - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "3", - name: "Room", - isSpace: false)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "3", + name: "Room", + isSpace: false)), isLastAdmin: false, isSelected: true), mediaProvider: MediaProviderMock(configuration: .init())) { } - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4", - name: "My Room", - isSpace: false)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4", + name: "My Room", + isSpace: false)), isLastAdmin: true, isSelected: false), mediaProvider: MediaProviderMock(configuration: .init())) { } - LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4", - name: "My Room", - isSpace: false)), + LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4", + name: "My Room", + isSpace: false)), isLastAdmin: true, isSelected: false), hideSelection: true, diff --git a/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceView.swift b/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceView.swift index 8fe7d77fa..5cc076807 100644 --- a/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceView.swift +++ b/ElementX/Sources/Screens/Spaces/LeaveSpace/View/LeaveSpaceView.swift @@ -64,11 +64,11 @@ struct LeaveSpaceView: View { context.viewState.leaveHandle.canLeave { LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) { Section { - ForEach(context.viewState.leaveHandle.rooms, id: \.spaceRoomProxy.id) { room in + ForEach(context.viewState.leaveHandle.rooms, id: \.spaceServiceRoom.id) { room in LeaveSpaceRoomDetailsCell(room: room, hideSelection: context.viewState.leaveHandle.mode == .onlyAdminRooms, mediaProvider: context.mediaProvider) { - context.send(viewAction: .toggleRoom(roomID: room.spaceRoomProxy.id)) + context.send(viewAction: .toggleRoom(roomID: room.spaceServiceRoom.id)) } .disabled(room.isLastAdmin) } @@ -136,27 +136,27 @@ struct LeaveSpaceView_Previews: PreviewProvider, TestablePreview { .previewDisplayName("Last Space Admin") } - static let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org", - name: "Engineering Team", - isSpace: true, - childrenCount: 30, - joinedMembersCount: 76, - heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], - topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", - joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) + static let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org", + name: "Engineering Team", + isSpace: true, + childrenCount: 30, + joinedMembersCount: 76, + heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], + topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", + joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel { let rooms: [LeaveSpaceRoom] = switch mode { case .manyRooms: .mockRooms case .onlyAdminRooms: .mockAdminRooms - case .noRooms: .mockSingleSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: false) - case .lastSpaceAdmin: .mockRoomsWithSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: true) + case .noRooms: .mockSingleSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: false) + case .lastSpaceAdmin: .mockRoomsWithSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: true) } - let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceRoomProxy.id, + let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceServiceRoom.id, leaveHandle: LeaveSpaceHandleSDKMock(.init(rooms: rooms))) - return LeaveSpaceViewModel(spaceName: spaceRoomProxy.name, + return LeaveSpaceViewModel(spaceName: spaceServiceRoom.name, canEditRolesAndPermissions: true, leaveHandle: leaveHandle, userIndicatorController: UserIndicatorControllerMock(), diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenModels.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenModels.swift index dc4333565..978eacf5e 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenModels.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenModels.swift @@ -18,7 +18,7 @@ struct SpaceListScreenViewState: BindableState { var userDisplayName: String? var userAvatarURL: URL? - var topLevelSpaces: [SpaceRoomProxyProtocol] + var topLevelSpaces: [SpaceServiceRoomProtocol] var selectedSpaceID: String? var isCreateSpaceEnabled: Bool diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift index ae3d9359a..765962f69 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/SpaceListScreenViewModel.swift @@ -65,8 +65,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie MXLog.info("View model: received view action: \(viewAction)") switch viewAction { - case .spaceAction(.select(let spaceRoomProxy)): - Task { await selectSpace(spaceRoomProxy) } + case .spaceAction(.select(let spaceServiceRoom)): + Task { await selectSpace(spaceServiceRoom) } case .spaceAction(.join): fatalError("There shouldn't be any unjoined spaces in the joined spaces list.") case .showSettings: @@ -86,8 +86,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie // MARK: - Private - private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { - switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) { + private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async { + switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) { case .success(let spaceRoomListProxy): actionsSubject.send(.selectSpace(spaceRoomListProxy)) case .failure(let error): diff --git a/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift index 594f35bbd..985c5d254 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceListScreen/View/SpaceListScreen.swift @@ -85,9 +85,9 @@ struct SpaceListScreen: View { } private var spaces: some View { - ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceRoomProxy in - SpaceRoomCell(spaceRoomProxy: spaceRoomProxy, - isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceID, + ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceServiceRoom in + SpaceRoomCell(spaceServiceRoom: spaceServiceRoom, + isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceID, mediaProvider: context.mediaProvider) { action in context.send(viewAction: .spaceAction(action)) } diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift index 63db22780..f00f3ed77 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenCoordinator.swift @@ -22,7 +22,7 @@ struct SpaceScreenCoordinatorParameters { enum SpaceScreenCoordinatorAction { case selectSpace(SpaceRoomListProxyProtocol) - case selectUnjoinedSpace(SpaceRoomProxyProtocol) + case selectUnjoinedSpace(SpaceServiceRoomProtocol) case selectRoom(roomID: String) case leftSpace case displayMembers(roomProxy: JoinedRoomProxyProtocol) @@ -60,8 +60,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol { switch action { case .selectSpace(let spaceRoomListProxy): actionsSubject.send(.selectSpace(spaceRoomListProxy)) - case .selectUnjoinedSpace(let spaceRoomProxy): - actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy)) + case .selectUnjoinedSpace(let spaceServiceRoom): + actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom)) case .selectRoom(let roomID): actionsSubject.send(.selectRoom(roomID: roomID)) case .leftSpace: diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift index 423bdaf3c..86bbbb279 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenModels.swift @@ -10,7 +10,7 @@ import Foundation enum SpaceScreenViewModelAction { case selectSpace(SpaceRoomListProxyProtocol) - case selectUnjoinedSpace(SpaceRoomProxyProtocol) + case selectUnjoinedSpace(SpaceServiceRoomProtocol) case selectRoom(roomID: String) case leftSpace case presentRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol) @@ -19,13 +19,13 @@ enum SpaceScreenViewModelAction { } struct SpaceScreenViewState: BindableState { - var space: SpaceRoomProxyProtocol + var space: SpaceServiceRoomProtocol var permalink: URL? var roomProxy: JoinedRoomProxyProtocol? var isPaginating = false - var rooms: [SpaceRoomProxyProtocol] + var rooms: [SpaceServiceRoomProtocol] var selectedSpaceRoomID: String? var joiningRoomIDs: Set = [] diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift index 30545eb3e..fee2d7f6e 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/SpaceScreenViewModel.swift @@ -37,12 +37,12 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc self.userIndicatorController = userIndicatorController self.appSettings = appSettings - super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceRoomProxyPublisher.value, + super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceServiceRoomPublisher.value, rooms: spaceRoomListProxy.spaceRoomsPublisher.value, selectedSpaceRoomID: selectedSpaceRoomPublisher.value), mediaProvider: userSession.mediaProvider) - spaceRoomListProxy.spaceRoomProxyPublisher + spaceRoomListProxy.spaceServiceRoomPublisher .receive(on: DispatchQueue.main) .weakAssign(to: \.state.space, on: self) .store(in: &cancellables) @@ -107,19 +107,19 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc MXLog.info("View model: received view action: \(viewAction)") switch viewAction { - case .spaceAction(.select(let spaceRoomProxy)): - if spaceRoomProxy.isSpace { - if spaceRoomProxy.state != .joined { - actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy)) + case .spaceAction(.select(let spaceServiceRoom)): + if spaceServiceRoom.isSpace { + if spaceServiceRoom.state != .joined { + actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom)) } else { - Task { await selectSpace(spaceRoomProxy) } + Task { await selectSpace(spaceServiceRoom) } } } else { // No need to check the join state, the room flow will show an appropriately configured join screen if needed. - actionsSubject.send(.selectRoom(roomID: spaceRoomProxy.id)) + actionsSubject.send(.selectRoom(roomID: spaceServiceRoom.id)) } - case .spaceAction(.join(let spaceRoomProxy)): - Task { await join(spaceRoomProxy) } + case .spaceAction(.join(let spaceServiceRoom)): + Task { await join(spaceServiceRoom) } case .leaveSpace: Task { await showLeaveSpaceConfirmation() } case .displayMembers(let roomProxy): @@ -136,11 +136,11 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc // MARK: - Private - private func join(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { - state.joiningRoomIDs.insert(spaceRoomProxy.id) - defer { state.joiningRoomIDs.remove(spaceRoomProxy.id) } + private func join(_ spaceServiceRoom: SpaceServiceRoomProtocol) async { + state.joiningRoomIDs.insert(spaceServiceRoom.id) + defer { state.joiningRoomIDs.remove(spaceServiceRoom.id) } - guard case .success = await clientProxy.joinRoom(spaceRoomProxy.id, via: spaceRoomProxy.via) else { + guard case .success = await clientProxy.joinRoom(spaceServiceRoom.id, via: spaceServiceRoom.via) else { showFailureIndicator() return } @@ -148,8 +148,8 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc // We don't want to show the space room after joining it this way 🤷‍♂️ } - private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { - switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) { + private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async { + switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) { case .success(let spaceRoomListProxy): actionsSubject.send(.selectSpace(spaceRoomListProxy)) case .failure(let error): diff --git a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift index 50eb87478..a398c1292 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceScreen/View/SpaceScreen.swift @@ -15,7 +15,7 @@ struct SpaceScreen: View { var body: some View { ScrollView { LazyVStack(spacing: 0) { - SpaceHeaderView(spaceRoomProxy: context.viewState.space, + SpaceHeaderView(spaceServiceRoom: context.viewState.space, mediaProvider: context.mediaProvider) rooms } @@ -32,10 +32,10 @@ struct SpaceScreen: View { @ViewBuilder var rooms: some View { - ForEach(context.viewState.rooms, id: \.id) { spaceRoomProxy in - SpaceRoomCell(spaceRoomProxy: spaceRoomProxy, - isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceRoomID, - isJoining: context.viewState.joiningRoomIDs.contains(spaceRoomProxy.id), + ForEach(context.viewState.rooms, id: \.id) { spaceServiceRoom in + SpaceRoomCell(spaceServiceRoom: spaceServiceRoom, + isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceRoomID, + isJoining: context.viewState.joiningRoomIDs.contains(spaceServiceRoom.id), mediaProvider: context.mediaProvider) { action in context.send(viewAction: .spaceAction(action)) } @@ -114,16 +114,16 @@ struct SpaceScreen_Previews: PreviewProvider, TestablePreview { } static func makeViewModel() -> SpaceScreenViewModel { - let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org", - name: "Engineering Team", - isSpace: true, - childrenCount: 30, - joinedMembersCount: 76, - heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], - topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", - canonicalAlias: "#engineering-team:element.io", - joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) - let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy, + let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org", + name: "Engineering Team", + isSpace: true, + childrenCount: 30, + joinedMembersCount: 76, + heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], + topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", + canonicalAlias: "#engineering-team:element.io", + joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) + let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom, initialSpaceRooms: .mockSpaceList)) let clientProxy = ClientProxyMock(.init()) diff --git a/ElementX/Sources/Services/Spaces/LeaveSpaceHandleProxy.swift b/ElementX/Sources/Services/Spaces/LeaveSpaceHandleProxy.swift index 791b281f3..f0a499ce8 100644 --- a/ElementX/Sources/Services/Spaces/LeaveSpaceHandleProxy.swift +++ b/ElementX/Sources/Services/Spaces/LeaveSpaceHandleProxy.swift @@ -35,7 +35,7 @@ final class LeaveSpaceHandleProxy { room.spaceRoom.roomId != spaceID else { return nil } - return .init(spaceRoomProxy: SpaceRoomProxy(spaceRoom: room.spaceRoom), + return .init(spaceServiceRoom: SpaceServiceRoom(spaceRoom: room.spaceRoom), isLastAdmin: room.isLastAdmin, isSelected: !room.isLastAdmin) } @@ -64,21 +64,21 @@ final class LeaveSpaceHandleProxy { } func toggleRoom(roomID: String) { - guard let room = rooms.first(where: { $0.spaceRoomProxy.id == roomID }) else { + guard let room = rooms.first(where: { $0.spaceServiceRoom.id == roomID }) else { return } room.isSelected.toggle() } func leave() async -> Result { - let selectedRoomIDs = rooms.filter(\.isSelected).map(\.spaceRoomProxy.id) + let selectedRoomIDs = rooms.filter(\.isSelected).map(\.spaceServiceRoom.id) do { return try await .success(leaveHandle.leave(roomIds: selectedRoomIDs + [id])) } catch { MXLog.error("Failed leaving space \(id): \(error)") rooms = rooms.filter { leaveRoom in - leaveHandle.rooms().contains { $0.spaceRoom.roomId == leaveRoom.spaceRoomProxy.id } + leaveHandle.rooms().contains { $0.spaceRoom.roomId == leaveRoom.spaceServiceRoom.id } } return .failure(.sdkError(error)) } @@ -86,12 +86,12 @@ final class LeaveSpaceHandleProxy { } @Observable class LeaveSpaceRoomDetails { - let spaceRoomProxy: SpaceRoomProxyProtocol + let spaceServiceRoom: SpaceServiceRoomProtocol let isLastAdmin: Bool var isSelected: Bool - init(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool, isSelected: Bool) { - self.spaceRoomProxy = spaceRoomProxy + init(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool, isSelected: Bool) { + self.spaceServiceRoom = spaceServiceRoom self.isLastAdmin = isLastAdmin self.isSelected = isSelected } diff --git a/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift b/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift index 9bb029516..30ca9b77f 100644 --- a/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift +++ b/ElementX/Sources/Services/Spaces/SpaceRoomListProxy.swift @@ -10,19 +10,19 @@ import Combine import MatrixRustSDK class SpaceRoomListProxy: SpaceRoomListProxyProtocol { - var id: String { spaceRoomProxyPublisher.value.id } + var id: String { spaceServiceRoomPublisher.value.id } private let spaceRoomList: SpaceRoomListProtocol - private var spaceRoomProxyHandle: TaskHandle? - private let spaceRoomProxySubject: CurrentValueSubject - var spaceRoomProxyPublisher: CurrentValuePublisher { - spaceRoomProxySubject.asCurrentValuePublisher() + private var spaceServiceRoomHandle: TaskHandle? + private let spaceServiceRoomSubject: CurrentValueSubject + var spaceServiceRoomPublisher: CurrentValuePublisher { + spaceServiceRoomSubject.asCurrentValuePublisher() } private var spaceRoomsHandle: TaskHandle? - private let spaceRoomsSubject = CurrentValueSubject<[SpaceRoomProxyProtocol], Never>([]) - var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { + private let spaceRoomsSubject = CurrentValueSubject<[SpaceServiceRoomProtocol], Never>([]) + var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { spaceRoomsSubject.asCurrentValuePublisher() } @@ -33,7 +33,7 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol { guard let spaceRoom = spaceRoomList.space() else { throw SpaceRoomListProxyError.missingSpace } self.spaceRoomList = spaceRoomList - spaceRoomProxySubject = .init(SpaceRoomProxy(spaceRoom: spaceRoom)) + spaceServiceRoomSubject = .init(SpaceServiceRoom(spaceRoom: spaceRoom)) let paginationStateSubject = CurrentValueSubject(spaceRoomList.paginationState()) paginationStatePublisher = paginationStateSubject.asCurrentValuePublisher() @@ -46,9 +46,9 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol { self?.handleUpdates(updates) }) - spaceRoomProxyHandle = spaceRoomList.subscribeToSpaceUpdates(listener: SDKListener { [weak self] spaceRoom in + spaceServiceRoomHandle = spaceRoomList.subscribeToSpaceUpdates(listener: SDKListener { [weak self] spaceRoom in guard let spaceRoom else { return } - self?.spaceRoomProxySubject.send(SpaceRoomProxy(spaceRoom: spaceRoom)) + self?.spaceServiceRoomSubject.send(SpaceServiceRoom(spaceRoom: spaceRoom)) }) } @@ -68,27 +68,27 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol { for update in updates { switch update { case .append(let spaceRooms): - rooms.append(contentsOf: spaceRooms.map(SpaceRoomProxy.init)) + rooms.append(contentsOf: spaceRooms.map(SpaceServiceRoom.init)) case .clear: rooms.removeAll() case .pushFront(let spaceRoom): - rooms.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: 0) + rooms.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: 0) case .pushBack(let spaceRoom): - rooms.append(SpaceRoomProxy(spaceRoom: spaceRoom)) + rooms.append(SpaceServiceRoom(spaceRoom: spaceRoom)) case .popFront: rooms.removeFirst() case .popBack: rooms.removeLast() case .insert(let index, let spaceRoom): - rooms.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: Int(index)) + rooms.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: Int(index)) case .set(let index, let spaceRoom): - rooms[Int(index)] = SpaceRoomProxy(spaceRoom: spaceRoom) + rooms[Int(index)] = SpaceServiceRoom(spaceRoom: spaceRoom) case .remove(let index): rooms.remove(at: Int(index)) case .truncate(let length): rooms.removeSubrange(Int(length).. { get } - var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { get } + var spaceServiceRoomPublisher: CurrentValuePublisher { get } + var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get } var paginationStatePublisher: CurrentValuePublisher { get } func paginate() async diff --git a/ElementX/Sources/Services/Spaces/SpaceRoomProxy.swift b/ElementX/Sources/Services/Spaces/SpaceRoomProxy.swift deleted file mode 100644 index 10d4251cc..000000000 --- a/ElementX/Sources/Services/Spaces/SpaceRoomProxy.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2025 Element Creations Ltd. -// Copyright 2025 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import MatrixRustSDK - -class SpaceRoomProxy: SpaceRoomProxyProtocol { - private let spaceRoom: SpaceRoom - - init(spaceRoom: SpaceRoom) { - self.spaceRoom = spaceRoom - } - - lazy var id = spaceRoom.roomId - var name: String { spaceRoom.displayName } - var rawName: String? { spaceRoom.rawName } - var avatarURL: URL? { spaceRoom.avatarUrl.flatMap(URL.init) } - - var isSpace: Bool { spaceRoom.roomType == .space } - var isDirect: Bool? { spaceRoom.isDirect } - var childrenCount: Int { Int(spaceRoom.childrenCount) } - - var joinedMembersCount: Int { Int(spaceRoom.numJoinedMembers) } - var heroes: [UserProfileProxy] { (spaceRoom.heroes ?? []).map(UserProfileProxy.init) } - var topic: String? { spaceRoom.topic } - var canonicalAlias: String? { spaceRoom.canonicalAlias } - - var joinRule: JoinRule? { spaceRoom.joinRule } - var worldReadable: Bool? { spaceRoom.worldReadable } - var guestCanJoin: Bool { spaceRoom.guestCanJoin } - var state: Membership? { spaceRoom.state } - var via: [String] { spaceRoom.via } -} diff --git a/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift b/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift index 6a275292b..c764c12fe 100644 --- a/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift +++ b/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift @@ -14,8 +14,8 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol { private let spaceService: SpaceServiceProtocol private var topLevelSpacesHandle: TaskHandle? - private let spacesSubject = CurrentValueSubject<[SpaceRoomProxyProtocol], Never>([]) - var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { + private let spacesSubject = CurrentValueSubject<[SpaceServiceRoomProtocol], Never>([]) + var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { spacesSubject.asCurrentValuePublisher() } @@ -40,9 +40,9 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol { } } - func spaceForIdentifier(spaceID: String) async -> Result { + func spaceForIdentifier(spaceID: String) async -> Result { do { - return try await .success(spaceService.getSpaceRoom(roomId: spaceID).map(SpaceRoomProxy.init)) + return try await .success(spaceService.getSpaceRoom(roomId: spaceID).map(SpaceServiceRoom.init)) } catch { MXLog.error("Failed getting space room for \(spaceID): \(error)") return .failure(.sdkError(error)) @@ -58,9 +58,9 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol { } } - func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { + func joinedParents(childID: String) async -> Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError> { do { - return try await .success(spaceService.joinedParentsOfChild(childId: childID).map(SpaceRoomProxy.init)) + return try await .success(spaceService.joinedParentsOfChild(childId: childID).map(SpaceServiceRoom.init)) } catch { MXLog.error("Failed to get joined parents for \(childID): \(error)") return .failure(.sdkError(error)) @@ -75,27 +75,27 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol { for update in updates { switch update { case .append(let spaceRooms): - spaces.append(contentsOf: spaceRooms.map(SpaceRoomProxy.init)) + spaces.append(contentsOf: spaceRooms.map(SpaceServiceRoom.init)) case .clear: spaces.removeAll() case .pushFront(let spaceRoom): - spaces.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: 0) + spaces.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: 0) case .pushBack(let spaceRoom): - spaces.append(SpaceRoomProxy(spaceRoom: spaceRoom)) + spaces.append(SpaceServiceRoom(spaceRoom: spaceRoom)) case .popFront: spaces.removeFirst() case .popBack: spaces.removeLast() case .insert(let index, let spaceRoom): - spaces.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: Int(index)) + spaces.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: Int(index)) case .set(let index, let spaceRoom): - spaces[Int(index)] = SpaceRoomProxy(spaceRoom: spaceRoom) + spaces[Int(index)] = SpaceServiceRoom(spaceRoom: spaceRoom) case .remove(let index): spaces.remove(at: Int(index)) case .truncate(let length): spaces.removeSubrange(Int(length).. { get } + var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get } func spaceRoomList(spaceID: String) async -> Result /// Returns a joined space given its identifier - func spaceForIdentifier(spaceID: String) async -> Result + func spaceForIdentifier(spaceID: String) async -> Result func leaveSpace(spaceID: String) async -> Result /// Returns all the parent spaces of a child that user has joined. - func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> + func joinedParents(childID: String) async -> Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError> } diff --git a/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift b/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift new file mode 100644 index 000000000..2a9a55ba4 --- /dev/null +++ b/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift @@ -0,0 +1,54 @@ +// +// Copyright 2025 Element Creations Ltd. +// Copyright 2025 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +struct SpaceServiceRoom: SpaceServiceRoomProtocol { + var id: String + var name: String + var rawName: String? + var avatarURL: URL? + + var isSpace: Bool + var isDirect: Bool? + var childrenCount: Int + + var joinedMembersCount: Int + var heroes: [UserProfileProxy] + var topic: String? + var canonicalAlias: String? + + var joinRule: JoinRule? + var worldReadable: Bool? + var guestCanJoin: Bool + var state: Membership? + var via: [String] + + init(spaceRoom: SpaceRoom) { + id = spaceRoom.roomId + name = spaceRoom.displayName + rawName = spaceRoom.rawName + avatarURL = spaceRoom.avatarUrl.flatMap(URL.init) + + isSpace = spaceRoom.roomType == .space + isDirect = spaceRoom.isDirect + childrenCount = Int(spaceRoom.childrenCount) + + joinedMembersCount = Int(spaceRoom.numJoinedMembers) + heroes = (spaceRoom.heroes ?? []).map(UserProfileProxy.init) + topic = spaceRoom.topic + canonicalAlias = spaceRoom.canonicalAlias + + joinRule = spaceRoom.joinRule + worldReadable = spaceRoom.worldReadable + guestCanJoin = spaceRoom.guestCanJoin + state = spaceRoom.state + via = spaceRoom.via + } +} diff --git a/ElementX/Sources/Services/Spaces/SpaceRoomProxyProtocol.swift b/ElementX/Sources/Services/Spaces/SpaceServiceRoomProtocol.swift similarity index 90% rename from ElementX/Sources/Services/Spaces/SpaceRoomProxyProtocol.swift rename to ElementX/Sources/Services/Spaces/SpaceServiceRoomProtocol.swift index ab8669366..4e611add1 100644 --- a/ElementX/Sources/Services/Spaces/SpaceRoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Spaces/SpaceServiceRoomProtocol.swift @@ -9,7 +9,7 @@ import Foundation import MatrixRustSDK -enum SpaceRoomProxyVisibility: Equatable { +enum SpaceServiceRoomVisibility: Equatable { case `public` case `private` case restricted @@ -17,7 +17,7 @@ enum SpaceRoomProxyVisibility: Equatable { } // sourcery: AutoMockable -protocol SpaceRoomProxyProtocol { +protocol SpaceServiceRoomProtocol { var id: String { get } var name: String { get } var rawName: String? { get } @@ -39,7 +39,7 @@ protocol SpaceRoomProxyProtocol { var via: [String] { get } } -extension SpaceRoomProxyProtocol { +extension SpaceServiceRoomProtocol { var avatar: RoomAvatar { if isSpace { .space(id: id, name: name, avatarURL: avatarURL) @@ -50,7 +50,7 @@ extension SpaceRoomProxyProtocol { } } - var visibility: SpaceRoomProxyVisibility? { + var visibility: SpaceServiceRoomVisibility? { switch joinRule { case .public: .public diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index bf6438d3f..1d80fe0fa 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -597,7 +597,7 @@ class MockScreen: Identifiable { deviceID: "MOCKCLIENT", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))), spaceServiceConfiguration: .init(topLevelSpaces: .mockSingleRoom), - roomPreviews: [SpaceRoomProxyProtocol].mockSpaceList.map(RoomPreviewProxyMock.init))) + roomPreviews: [SpaceServiceRoomProtocol].mockSpaceList.map(RoomPreviewProxyMock.init))) // The tab bar remains hidden for the non-spaces tests as we don't supply any mock spaces. let spaceServiceProxy = SpaceServiceProxyMock(id == .userSessionSpacesFlow ? .populated : .init()) diff --git a/UnitTests/Sources/HomeScreenViewModelTests.swift b/UnitTests/Sources/HomeScreenViewModelTests.swift index a1fd21162..7e1ee254d 100644 --- a/UnitTests/Sources/HomeScreenViewModelTests.swift +++ b/UnitTests/Sources/HomeScreenViewModelTests.swift @@ -311,7 +311,7 @@ class HomeScreenViewModelTests: XCTestCase { XCTAssertEqual(invitedRoomIDs.count, 2) let deferred = deferFulfillment(viewModel.actions) { - $0 == .presentSpace(SpaceRoomListProxyMock(.init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: invitedRoomIDs[0], isSpace: true))))) + $0 == .presentSpace(SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: invitedRoomIDs[0], isSpace: true))))) } context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0])) try await deferred.fulfill() @@ -408,7 +408,7 @@ class HomeScreenViewModelTests: XCTestCase { let spaceServiceProxy = SpaceServiceProxyMock(.init()) spaceServiceProxy.spaceRoomListSpaceIDClosure = { spaceID in - .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: spaceID, isSpace: true))))) + .success(SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: spaceID, isSpace: true))))) } clientProxy.underlyingSpaceService = spaceServiceProxy case nil: diff --git a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift index e35620f70..f7840eb38 100644 --- a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift +++ b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift @@ -29,7 +29,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testSetSingleJoinedSpaceMembersAccess() async throws { - let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom let space = singleRoom[0] setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public) @@ -60,7 +60,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testSetSingleJoinedAskToJoinWithSpaceMembersAccess() async throws { - let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom let space = singleRoom[0] setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public) @@ -91,7 +91,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws { - let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom let space = singleRoom[0] setupViewModel(joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomId: space.id)])) @@ -122,7 +122,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testMultipleKnownSpacesMembersSelection() async throws { - let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 + let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2 setupViewModel(joinedParentSpaces: spaces, joinRule: .public) let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 } @@ -166,7 +166,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testMultipleKnownAskToJoinSpacesMembersSelection() async throws { - let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 + let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2 setupViewModel(joinedParentSpaces: spaces, joinRule: .public) let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 } @@ -210,7 +210,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testMultipleSpacesMembersSelection() async throws { - let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 + let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2 setupViewModel(joinedParentSpaces: spaces, joinRule: .restricted(rules: [.roomMembership(roomId: "unknownSpaceID")])) @@ -256,8 +256,8 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { } func testMultipleSpacesMembersSelectionWithAnExistingNonParentButJoinedSpace() async throws { - let joinedParentSpaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 - let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let joinedParentSpaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2 + let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom let space = singleRoom[0] let allSpaces = joinedParentSpaces + singleRoom setupViewModel(joinedParentSpaces: joinedParentSpaces, @@ -319,7 +319,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { func testEmptySpaceMembersSelectionWithJoinedParentEdgeCase() async throws { // Edge case where there is one available joined parent but the room has a restricted join rule. // With no space ids in it - let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom setupViewModel(joinedParentSpaces: singleRoom, joinRule: .restricted(rules: [])) @@ -424,8 +424,8 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase { // MARK: - Helpers - private func setupViewModel(joinedParentSpaces: [SpaceRoomProxyProtocol], - topLevelSpaces: [SpaceRoomProxyProtocol] = [], + private func setupViewModel(joinedParentSpaces: [SpaceServiceRoomProtocol], + topLevelSpaces: [SpaceServiceRoomProtocol] = [], joinRule: JoinRule) { let appSettings = AppSettings() appSettings.spaceSettingsEnabled = true diff --git a/UnitTests/Sources/SpaceListScreenViewModelTests.swift b/UnitTests/Sources/SpaceListScreenViewModelTests.swift index 37c59b8b2..44ea1180e 100644 --- a/UnitTests/Sources/SpaceListScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceListScreenViewModelTests.swift @@ -13,7 +13,7 @@ import XCTest @MainActor class SpaceListScreenViewModelTests: XCTestCase { - var topLevelSpacesSubject: CurrentValueSubject<[SpaceRoomProxyProtocol], Never>! + var topLevelSpacesSubject: CurrentValueSubject<[SpaceServiceRoomProtocol], Never>! var spaceServiceProxy: SpaceServiceProxyMock! var appSettings: AppSettings! @@ -47,7 +47,7 @@ class SpaceListScreenViewModelTests: XCTestCase { deferred = deferFulfillment(context.observe(\.viewState.topLevelSpaces)) { $0.count == 1 } topLevelSpacesSubject.send([ - SpaceRoomProxyMock(.init(isSpace: true)) + SpaceServiceRoomMock(.init(isSpace: true)) ]) try await deferred.fulfill() XCTAssertEqual(context.viewState.topLevelSpaces.count, 1) @@ -97,15 +97,15 @@ class SpaceListScreenViewModelTests: XCTestCase { let userSession = UserSessionMock(.init(clientProxy: clientProxy)) topLevelSpacesSubject = .init([ - SpaceRoomProxyMock(.init(id: "space1", isSpace: true)), - SpaceRoomProxyMock(.init(id: "space2", isSpace: true)), - SpaceRoomProxyMock(.init(id: "space3", isSpace: true)) + SpaceServiceRoomMock(.init(id: "space1", isSpace: true)), + SpaceServiceRoomMock(.init(id: "space2", isSpace: true)), + SpaceServiceRoomMock(.init(id: "space3", isSpace: true)) ]) spaceServiceProxy = SpaceServiceProxyMock(.init()) spaceServiceProxy.topLevelSpacesPublisher = topLevelSpacesSubject.asCurrentValuePublisher() spaceServiceProxy.spaceRoomListSpaceIDClosure = { [topLevelSpacesSubject] spaceID in - guard let spaceRoomProxy = topLevelSpacesSubject?.value.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } - return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy))) + guard let spaceServiceRoom = topLevelSpacesSubject?.value.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } + return .success(SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom))) } clientProxy.spaceService = spaceServiceProxy diff --git a/UnitTests/Sources/SpaceScreenViewModelTests.swift b/UnitTests/Sources/SpaceScreenViewModelTests.swift index 757ba0895..445391ae6 100644 --- a/UnitTests/Sources/SpaceScreenViewModelTests.swift +++ b/UnitTests/Sources/SpaceScreenViewModelTests.swift @@ -16,7 +16,7 @@ import MatrixRustSDKMocks @MainActor class SpaceScreenViewModelTests: XCTestCase { var spaceRoomListProxy: SpaceRoomListProxyMock! - let mockSpaceRooms = [SpaceRoomProxyProtocol].mockSpaceList + let mockSpaceRooms = [SpaceServiceRoomProtocol].mockSpaceList var clientProxy: ClientProxyMock! var paginationStateSubject: CurrentValueSubject = .init(.idle(endReached: true)) var rustLeaveHandle: LeaveSpaceHandleSDKMock! @@ -118,7 +118,7 @@ class SpaceScreenViewModelTests: XCTestCase { let action = try await deferred.fulfill() switch action { - case .selectUnjoinedSpace(let spaceRoomProxy) where spaceRoomProxy.id == selectedSpace.id: + case .selectUnjoinedSpace(let spaceServiceRoom) where spaceServiceRoom.id == selectedSpace.id: break default: XCTFail("The action should select the space.") @@ -195,7 +195,7 @@ class SpaceScreenViewModelTests: XCTestCase { leaveSpaceViewModel.context.send(viewAction: .deselectAll) XCTAssertEqual(handle.selectedCount, 0, "Deselecting all should result in no selected rooms.") - leaveSpaceViewModel.context.send(viewAction: .toggleRoom(roomID: firstSelectedRoom.spaceRoomProxy.id)) + leaveSpaceViewModel.context.send(viewAction: .toggleRoom(roomID: firstSelectedRoom.spaceServiceRoom.id)) XCTAssertEqual(handle.selectedCount, 1, "Toggling a room should result in 1 selected room") // Confirming the leave should leave the selected room and then the space. @@ -205,21 +205,21 @@ class SpaceScreenViewModelTests: XCTestCase { XCTAssertNil(context.leaveSpaceViewModel) XCTAssertTrue(rustLeaveHandle.leaveRoomIdsCalled) XCTAssertEqual(rustLeaveHandle.leaveRoomIdsReceivedRoomIds, - [firstSelectedRoom.spaceRoomProxy.id, spaceRoomListProxy.id], + [firstSelectedRoom.spaceServiceRoom.id, spaceRoomListProxy.id], "Confirming the leave should first leave the selected room and then the space.") } // MARK: - Helpers - private func setupViewModel(paginationResponses: [[SpaceRoomProxyProtocol]] = []) { - spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: SpaceRoomProxyMock(.init(isSpace: true)), + private func setupViewModel(paginationResponses: [[SpaceServiceRoomProtocol]] = []) { + spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(isSpace: true)), paginationStateSubject: paginationStateSubject, paginationResponses: paginationResponses)) let spaceServiceProxy = SpaceServiceProxyMock(.init()) spaceServiceProxy.spaceRoomListSpaceIDClosure = { [mockSpaceRooms] spaceID in - guard let spaceRoomProxy = mockSpaceRooms.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } - return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy))) + guard let spaceServiceRoom = mockSpaceRooms.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } + return .success(SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom))) } let rustLeaveHandle = LeaveSpaceHandleSDKMock(.init()) spaceServiceProxy.leaveSpaceSpaceIDClosure = { spaceID in