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.
This commit is contained in:
Doug
2026-01-13 12:00:20 +00:00
committed by GitHub
parent de1753a766
commit 334df3f5cd
43 changed files with 620 additions and 604 deletions
+12 -12
View File
@@ -216,7 +216,6 @@
24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; }; 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; };
24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; }; 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; };
24C32D7EF94ECF9081638DF6 /* RemotePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A05E85E4872C3221C5C287 /* RemotePreference.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 */; }; 250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11397904D19CFF0E3689F0E /* SpaceScreenModels.swift */; };
2538350683F421AB620AA950 /* AccessibleLongPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307C3E5B9B189497D3250E23 /* AccessibleLongPress.swift */; }; 2538350683F421AB620AA950 /* AccessibleLongPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307C3E5B9B189497D3250E23 /* AccessibleLongPress.swift */; };
25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.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 */; }; 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; };
60ED66E63A169E47489348A8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; 60ED66E63A169E47489348A8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; };
611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */; }; 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 */; }; 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; };
6183BD3916CAA7134B6070D2 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 6183BD3916CAA7134B6070D2 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.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 */; }; 90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE40D4A5DD857AC16EED945A /* URLSession.swift */; };
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.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 */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; };
915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; };
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.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 */; }; BDED6DA7AD1E76018C424143 /* LegalInformationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C34667458773B02AB5FB0B2 /* LegalInformationScreenViewModel.swift */; };
BDFF0AEBF57B5B124062DAEF /* GeneratedAccessibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CEB4590CCF70F0E3C0B171 /* GeneratedAccessibilityTests.swift */; }; BDFF0AEBF57B5B124062DAEF /* GeneratedAccessibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CEB4590CCF70F0E3C0B171 /* GeneratedAccessibilityTests.swift */; };
BE011C4473B9A8F12CBFE92A /* UserDetailsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F58D94C936A1B731D78DE1 /* UserDetailsEditScreenViewModelTests.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 */; }; BE8E5985771DF9137C6CE89A /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */; };
BEC6DFEA506085D3027E353C /* MediaEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */; }; BEC6DFEA506085D3027E353C /* MediaEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */; };
BED59052E5C5163D2B065CA6 /* EventTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A81FD0C60175FA081EB19AD /* EventTimelineItem.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 */; }; C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; };
C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */; }; C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */; };
C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.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 */; }; C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; };
C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */; }; C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */; };
C797C0B4CF45C66CD1921252 /* SoftLogoutScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC43313F21511C853D34544E /* SoftLogoutScreenViewModelTests.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 */; }; F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; };
F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25586C0ADB814FEE9897DCAA /* BugReportHook.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 */; }; 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 */; }; F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; };
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; }; F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; };
F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.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 = "<group>"; }; 34ED3AB7E0287552A5648AB3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = "<group>"; };
353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConsentState.swift; sourceTree = "<group>"; }; 353024006CB726E9F9187B3A /* AnalyticsConsentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsConsentState.swift; sourceTree = "<group>"; };
3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = "<group>"; }; 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = "<group>"; };
355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxy.swift; sourceTree = "<group>"; };
35A057BA9BE0F079784CD061 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 35A057BA9BE0F079784CD061 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
@@ -1996,12 +1995,14 @@
536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; }; 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModel.swift; sourceTree = "<group>"; }; 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModel.swift; sourceTree = "<group>"; };
53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = "<group>"; }; 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = "<group>"; };
5416FE342A1E6A1B6D028999 /* SpaceServiceRoomProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceRoomProtocol.swift; sourceTree = "<group>"; };
5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = "<group>"; }; 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = "<group>"; };
5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = "<group>"; }; 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = "<group>"; };
54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = "<group>"; }; 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = "<group>"; };
54A7923F0115CF17ABC8047F /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/SAS.strings; sourceTree = "<group>"; }; 54A7923F0115CF17ABC8047F /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/SAS.strings; sourceTree = "<group>"; };
54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReactionsView.swift; sourceTree = "<group>"; }; 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReactionsView.swift; sourceTree = "<group>"; };
54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
5530D3541C8832D858EB755A /* SpaceRoomInfoMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomInfoMock.swift; sourceTree = "<group>"; };
5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenViewModelTests.swift; sourceTree = "<group>"; }; 5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenViewModelTests.swift; sourceTree = "<group>"; };
55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = "<group>"; }; 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSender.swift; sourceTree = "<group>"; };
55B3BF242C93CD32C4C3E08D /* ChatsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsFlowCoordinator.swift; sourceTree = "<group>"; }; 55B3BF242C93CD32C4C3E08D /* ChatsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsFlowCoordinator.swift; sourceTree = "<group>"; };
@@ -2393,7 +2394,6 @@
A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; }; A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = "<group>"; }; A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = "<group>"; };
A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = "<group>"; }; A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = "<group>"; };
A01F2E9FD8FF95AB89A345E6 /* SpaceRoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxyProtocol.swift; sourceTree = "<group>"; };
A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = "<group>"; }; A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = "<group>"; };
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
A07B011547B201A836C03052 /* EncryptionResetFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetFlowCoordinator.swift; sourceTree = "<group>"; }; A07B011547B201A836C03052 /* EncryptionResetFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetFlowCoordinator.swift; sourceTree = "<group>"; };
@@ -2480,7 +2480,6 @@
AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilderTests.swift; sourceTree = "<group>"; }; AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilderTests.swift; sourceTree = "<group>"; };
AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = "<group>"; }; AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = "<group>"; };
AF2E6ADAE685F4109B1FE795 /* TimelineThreadSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineThreadSummaryView.swift; sourceTree = "<group>"; }; AF2E6ADAE685F4109B1FE795 /* TimelineThreadSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineThreadSummaryView.swift; sourceTree = "<group>"; };
AF771312D208C8002A2F05C4 /* SpaceRoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxyMock.swift; sourceTree = "<group>"; };
AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; }; AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; };
AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineView.swift; sourceTree = "<group>"; }; AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineView.swift; sourceTree = "<group>"; };
AFEF489B8E2450E2BA1A314E /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SAS.strings; sourceTree = "<group>"; }; AFEF489B8E2450E2BA1A314E /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SAS.strings; sourceTree = "<group>"; };
@@ -2643,6 +2642,7 @@
CC666DAE98245269775329B2 /* RoomMembersFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersFlowCoordinatorTests.swift; sourceTree = "<group>"; }; CC666DAE98245269775329B2 /* RoomMembersFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersFlowCoordinatorTests.swift; sourceTree = "<group>"; };
CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; }; CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = "<group>"; }; CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = "<group>"; };
CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceRoom.swift; sourceTree = "<group>"; };
CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenViewModel.swift; sourceTree = "<group>"; }; CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenViewModel.swift; sourceTree = "<group>"; };
CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreen.swift; sourceTree = "<group>"; }; CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreen.swift; sourceTree = "<group>"; };
CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItemContent.swift; sourceTree = "<group>"; }; CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItemContent.swift; sourceTree = "<group>"; };
@@ -3640,8 +3640,8 @@
FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */, FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */,
4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */, 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */,
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */,
5530D3541C8832D858EB755A /* SpaceRoomInfoMock.swift */,
7DB2A5FF1E68BA580A20D405 /* SpaceRoomListProxyMock.swift */, 7DB2A5FF1E68BA580A20D405 /* SpaceRoomListProxyMock.swift */,
AF771312D208C8002A2F05C4 /* SpaceRoomProxyMock.swift */,
EF36FC3DE25B20B7FA91F1FD /* SpaceServiceProxyMock.swift */, EF36FC3DE25B20B7FA91F1FD /* SpaceServiceProxyMock.swift */,
B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */, B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */,
62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */, 62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */,
@@ -5703,10 +5703,10 @@
75B3CE05643C7791D46AC54B /* LeaveSpaceHandleProxy.swift */, 75B3CE05643C7791D46AC54B /* LeaveSpaceHandleProxy.swift */,
4B2B564CA6570E1487A7C7CC /* SpaceRoomListProxy.swift */, 4B2B564CA6570E1487A7C7CC /* SpaceRoomListProxy.swift */,
EACD4855BDAD0799FD86B7B5 /* SpaceRoomListProxyProtocol.swift */, EACD4855BDAD0799FD86B7B5 /* SpaceRoomListProxyProtocol.swift */,
355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */,
A01F2E9FD8FF95AB89A345E6 /* SpaceRoomProxyProtocol.swift */,
226A56746AD99ABDA97189E1 /* SpaceServiceProxy.swift */, 226A56746AD99ABDA97189E1 /* SpaceServiceProxy.swift */,
C57DB49B8426AA721BF85D83 /* SpaceServiceProxyProtocol.swift */, C57DB49B8426AA721BF85D83 /* SpaceServiceProxyProtocol.swift */,
CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */,
5416FE342A1E6A1B6D028999 /* SpaceServiceRoomProtocol.swift */,
); );
path = Spaces; path = Spaces;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -8546,12 +8546,10 @@
F396470968764E2C3EDA92DA /* SpaceListScreenViewModel.swift in Sources */, F396470968764E2C3EDA92DA /* SpaceListScreenViewModel.swift in Sources */,
368EC173453FB805C677BFEF /* SpaceListScreenViewModelProtocol.swift in Sources */, 368EC173453FB805C677BFEF /* SpaceListScreenViewModelProtocol.swift in Sources */,
9B84F55288AB98783C11CC49 /* SpaceRoomCell.swift in Sources */, 9B84F55288AB98783C11CC49 /* SpaceRoomCell.swift in Sources */,
913BCABB99796F82E3D8D93D /* SpaceRoomInfoMock.swift in Sources */,
0DAB08C117E0391F3ADB2031 /* SpaceRoomListProxy.swift in Sources */, 0DAB08C117E0391F3ADB2031 /* SpaceRoomListProxy.swift in Sources */,
9FBF0078657CA4F2A9747E98 /* SpaceRoomListProxyMock.swift in Sources */, 9FBF0078657CA4F2A9747E98 /* SpaceRoomListProxyMock.swift in Sources */,
2EAA1B35D9CA24F090F48792 /* SpaceRoomListProxyProtocol.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 */, 6CAADDC6318E41C7D7AA9526 /* SpaceScreen.swift in Sources */,
EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */, EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */,
250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */, 250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */,
@@ -8560,6 +8558,8 @@
94C2B531B96493B68B976E5F /* SpaceServiceProxy.swift in Sources */, 94C2B531B96493B68B976E5F /* SpaceServiceProxy.swift in Sources */,
A2091F4B1332D9BF273B09D5 /* SpaceServiceProxyMock.swift in Sources */, A2091F4B1332D9BF273B09D5 /* SpaceServiceProxyMock.swift in Sources */,
DB5200B87C4CE9DF0024AC4E /* SpaceServiceProxyProtocol.swift in Sources */, DB5200B87C4CE9DF0024AC4E /* SpaceServiceProxyProtocol.swift in Sources */,
612196AF7826846A50C07FA6 /* SpaceServiceRoom.swift in Sources */,
F4F29FF972C0C8B38757B2DD /* SpaceServiceRoomProtocol.swift in Sources */,
D0E257557DAC8A34C7B52A9F /* SpaceSettingsFlowCoordinator.swift in Sources */, D0E257557DAC8A34C7B52A9F /* SpaceSettingsFlowCoordinator.swift in Sources */,
383063A7924F06D54BA9B24C /* SpaceSettingsScreen.swift in Sources */, 383063A7924F06D54BA9B24C /* SpaceSettingsScreen.swift in Sources */,
9DB4B303ECC05F0F33582594 /* SpacesAnnouncementSheetView.swift in Sources */, 9DB4B303ECC05F0F33582594 /* SpacesAnnouncementSheetView.swift in Sources */,
@@ -18,12 +18,12 @@ enum SpaceFlowCoordinatorAction {
enum SpaceFlowCoordinatorEntryPoint { enum SpaceFlowCoordinatorEntryPoint {
case space(SpaceRoomListProxyProtocol) case space(SpaceRoomListProxyProtocol)
case joinSpace(SpaceRoomProxyProtocol) case joinSpace(SpaceServiceRoomProtocol)
var spaceID: String { var spaceID: String {
switch self { switch self {
case .space(let spaceRoomListProxy): spaceRoomListProxy.id 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 { switch action {
case .selectSpace(let spaceRoomListProxy): case .selectSpace(let spaceRoomListProxy):
stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.space(spaceRoomListProxy)) stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.space(spaceRoomListProxy))
case .selectUnjoinedSpace(let spaceRoomProxy): case .selectUnjoinedSpace(let spaceServiceRoom):
stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.joinSpace(spaceRoomProxy)) stateMachine.tryEvent(.startChildFlow, userInfo: SpaceFlowCoordinatorEntryPoint.joinSpace(spaceServiceRoom))
case .selectRoom(let roomID): case .selectRoom(let roomID):
stateMachine.tryEvent(.startRoomFlow(roomID: roomID)) stateMachine.tryEvent(.startRoomFlow(roomID: roomID))
case .leftSpace: case .leftSpace:
@@ -322,9 +322,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
} }
private func presentJoinSpaceScreen() { 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, userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController, userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings) appSettings: flowParameters.appSettings)
+2 -2
View File
@@ -123,8 +123,8 @@ extension ClientProxyMock {
roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock()) roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock())
return .joined(roomProxy) return .joined(roomProxy)
} }
} else if let spaceRoomProxy = configuration.spaceServiceConfiguration.topLevelSpaces.first(where: { $0.id == identifier }) { } else if let spaceServiceRoom = configuration.spaceServiceConfiguration.topLevelSpaces.first(where: { $0.id == identifier }) {
let roomProxy = await JoinedRoomProxyMock(.init(id: spaceRoomProxy.id, name: spaceRoomProxy.name, isSpace: spaceRoomProxy.isSpace)) let roomProxy = await JoinedRoomProxyMock(.init(id: spaceServiceRoom.id, name: spaceServiceRoom.name, isSpace: spaceServiceRoom.isSpace))
roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock()) roomProxy.loadOrFetchEventDetailsForReturnValue = .success(TimelineEventSDKMock())
return .joined(roomProxy) return .joined(roomProxy)
} else { } else {
@@ -16721,16 +16721,16 @@ class SpaceRoomListProxyMock: SpaceRoomListProxyProtocol, @unchecked Sendable {
set(value) { underlyingId = value } set(value) { underlyingId = value }
} }
var underlyingId: String! var underlyingId: String!
var spaceRoomProxyPublisher: CurrentValuePublisher<SpaceRoomProxyProtocol, Never> { var spaceServiceRoomPublisher: CurrentValuePublisher<SpaceServiceRoomProtocol, Never> {
get { return underlyingSpaceRoomProxyPublisher } get { return underlyingSpaceServiceRoomPublisher }
set(value) { underlyingSpaceRoomProxyPublisher = value } set(value) { underlyingSpaceServiceRoomPublisher = value }
} }
var underlyingSpaceRoomProxyPublisher: CurrentValuePublisher<SpaceRoomProxyProtocol, Never>! var underlyingSpaceServiceRoomPublisher: CurrentValuePublisher<SpaceServiceRoomProtocol, Never>!
var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> {
get { return underlyingSpaceRoomsPublisher } get { return underlyingSpaceRoomsPublisher }
set(value) { underlyingSpaceRoomsPublisher = value } set(value) { underlyingSpaceRoomsPublisher = value }
} }
var underlyingSpaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never>! var underlyingSpaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never>!
var paginationStatePublisher: CurrentValuePublisher<SpaceRoomListPaginationState, Never> { var paginationStatePublisher: CurrentValuePublisher<SpaceRoomListPaginationState, Never> {
get { return underlyingPaginationStatePublisher } get { return underlyingPaginationStatePublisher }
set(value) { underlyingPaginationStatePublisher = value } set(value) { underlyingPaginationStatePublisher = value }
@@ -16773,55 +16773,12 @@ class SpaceRoomListProxyMock: SpaceRoomListProxyProtocol, @unchecked Sendable {
await paginateClosure?() 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 { class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> {
get { return underlyingTopLevelSpacesPublisher } get { return underlyingTopLevelSpacesPublisher }
set(value) { underlyingTopLevelSpacesPublisher = value } set(value) { underlyingTopLevelSpacesPublisher = value }
} }
var underlyingTopLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never>! var underlyingTopLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never>!
//MARK: - spaceRoomList //MARK: - spaceRoomList
@@ -16925,13 +16882,13 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
var spaceForIdentifierSpaceIDReceivedSpaceID: String? var spaceForIdentifierSpaceIDReceivedSpaceID: String?
var spaceForIdentifierSpaceIDReceivedInvocations: [String] = [] var spaceForIdentifierSpaceIDReceivedInvocations: [String] = []
var spaceForIdentifierSpaceIDUnderlyingReturnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>! var spaceForIdentifierSpaceIDUnderlyingReturnValue: Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError>!
var spaceForIdentifierSpaceIDReturnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>! { var spaceForIdentifierSpaceIDReturnValue: Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError>! {
get { get {
if Thread.isMainThread { if Thread.isMainThread {
return spaceForIdentifierSpaceIDUnderlyingReturnValue return spaceForIdentifierSpaceIDUnderlyingReturnValue
} else { } else {
var returnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>? = nil var returnValue: Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError>? = nil
DispatchQueue.main.sync { DispatchQueue.main.sync {
returnValue = spaceForIdentifierSpaceIDUnderlyingReturnValue returnValue = spaceForIdentifierSpaceIDUnderlyingReturnValue
} }
@@ -16949,9 +16906,9 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
} }
} }
} }
var spaceForIdentifierSpaceIDClosure: ((String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>)? var spaceForIdentifierSpaceIDClosure: ((String) async -> Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError>)?
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError> { func spaceForIdentifier(spaceID: String) async -> Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError> {
spaceForIdentifierSpaceIDCallsCount += 1 spaceForIdentifierSpaceIDCallsCount += 1
spaceForIdentifierSpaceIDReceivedSpaceID = spaceID spaceForIdentifierSpaceIDReceivedSpaceID = spaceID
DispatchQueue.main.async { DispatchQueue.main.async {
@@ -17065,13 +17022,13 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
var joinedParentsChildIDReceivedChildID: String? var joinedParentsChildIDReceivedChildID: String?
var joinedParentsChildIDReceivedInvocations: [String] = [] var joinedParentsChildIDReceivedInvocations: [String] = []
var joinedParentsChildIDUnderlyingReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! var joinedParentsChildIDUnderlyingReturnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>!
var joinedParentsChildIDReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! { var joinedParentsChildIDReturnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>! {
get { get {
if Thread.isMainThread { if Thread.isMainThread {
return joinedParentsChildIDUnderlyingReturnValue return joinedParentsChildIDUnderlyingReturnValue
} else { } else {
var returnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>? = nil var returnValue: Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>? = nil
DispatchQueue.main.sync { DispatchQueue.main.sync {
returnValue = joinedParentsChildIDUnderlyingReturnValue 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 joinedParentsChildIDCallsCount += 1
joinedParentsChildIDReceivedChildID = childID joinedParentsChildIDReceivedChildID = childID
DispatchQueue.main.async { 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 { class StaticRoomSummaryProviderMock: StaticRoomSummaryProviderProtocol, @unchecked Sendable {
var statePublisher: CurrentValuePublisher<RoomSummaryProviderState, Never> { var statePublisher: CurrentValuePublisher<RoomSummaryProviderState, Never> {
get { return underlyingStatePublisher } get { return underlyingStatePublisher }
@@ -98,17 +98,17 @@ extension RoomPreviewProxyMock {
underlyingOwnMembershipDetails = roomMembershipDetails underlyingOwnMembershipDetails = roomMembershipDetails
} }
convenience init(spaceRoomProxy: SpaceRoomProxyProtocol) { convenience init(spaceServiceRoom: SpaceServiceRoomProtocol) {
self.init(Configuration(roomID: spaceRoomProxy.id, self.init(Configuration(roomID: spaceServiceRoom.id,
canonicalAlias: spaceRoomProxy.canonicalAlias ?? "", canonicalAlias: spaceServiceRoom.canonicalAlias ?? "",
name: spaceRoomProxy.name, name: spaceServiceRoom.name,
topic: spaceRoomProxy.topic ?? "", topic: spaceServiceRoom.topic ?? "",
avatarURL: spaceRoomProxy.avatarURL?.absoluteString ?? "", avatarURL: spaceServiceRoom.avatarURL?.absoluteString ?? "",
numJoinedMembers: UInt64(spaceRoomProxy.joinedMembersCount), numJoinedMembers: UInt64(spaceServiceRoom.joinedMembersCount),
numActiveMembers: UInt64(spaceRoomProxy.joinedMembersCount), numActiveMembers: UInt64(spaceServiceRoom.joinedMembersCount),
roomType: spaceRoomProxy.isSpace ? .space : .room, roomType: spaceServiceRoom.isSpace ? .space : .room,
membership: nil, membership: nil,
joinRule: spaceRoomProxy.joinRule ?? .restricted(rules: []), joinRule: spaceServiceRoom.joinRule ?? .restricted(rules: []),
isDirect: false)) isDirect: false))
} }
} }
@@ -23,17 +23,17 @@ extension LeaveSpaceHandleSDKMock {
} }
extension [LeaveSpaceRoom] { extension [LeaveSpaceRoom] {
static func mockRoomsWithSpace(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { static func mockRoomsWithSpace(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] {
mockRooms + mockSingleSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: isLastAdmin) mockRooms + mockSingleSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: isLastAdmin)
} }
static func mockSingleSpace(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] { static func mockSingleSpace(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool) -> [LeaveSpaceRoom] {
[LeaveSpaceRoom(spaceRoom: SpaceRoom(id: spaceRoomProxy.id, [LeaveSpaceRoom(spaceRoom: SpaceRoom(id: spaceServiceRoom.id,
name: spaceRoomProxy.name, name: spaceServiceRoom.name,
avatarURL: spaceRoomProxy.avatarURL, avatarURL: spaceServiceRoom.avatarURL,
isSpace: true, isSpace: true,
memberCount: UInt64(spaceRoomProxy.joinedMembersCount), memberCount: UInt64(spaceServiceRoom.joinedMembersCount),
joinRule: spaceRoomProxy.joinRule), joinRule: spaceServiceRoom.joinRule),
isLastAdmin: isLastAdmin)] isLastAdmin: isLastAdmin)]
} }
@@ -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))
}
}
@@ -12,16 +12,16 @@ import MatrixRustSDK
extension SpaceRoomListProxyMock { extension SpaceRoomListProxyMock {
class Configuration { class Configuration {
var spaceRoomProxy: SpaceRoomProxyProtocol var spaceServiceRoom: SpaceServiceRoomProtocol
var initialSpaceRooms: [SpaceRoomProxyProtocol] var initialSpaceRooms: [SpaceServiceRoomProtocol]
var paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never> var paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never>
var paginationResponses: [[SpaceRoomProxyProtocol]] var paginationResponses: [[SpaceServiceRoomProtocol]]
init(spaceRoomProxy: SpaceRoomProxyProtocol, init(spaceServiceRoom: SpaceServiceRoomProtocol,
initialSpaceRooms: [SpaceRoomProxyProtocol] = [], initialSpaceRooms: [SpaceServiceRoomProtocol] = [],
paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never> = .init(.idle(endReached: true)), paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never> = .init(.idle(endReached: true)),
paginationResponses: [[SpaceRoomProxyProtocol]] = []) { paginationResponses: [[SpaceServiceRoomProtocol]] = []) {
self.spaceRoomProxy = spaceRoomProxy self.spaceServiceRoom = spaceServiceRoom
self.initialSpaceRooms = initialSpaceRooms self.initialSpaceRooms = initialSpaceRooms
self.paginationStateSubject = paginationStateSubject self.paginationStateSubject = paginationStateSubject
self.paginationResponses = paginationResponses self.paginationResponses = paginationResponses
@@ -31,10 +31,10 @@ extension SpaceRoomListProxyMock {
convenience init(_ configuration: Configuration) { convenience init(_ configuration: Configuration) {
self.init() self.init()
let spaceRoomsSubject: CurrentValueSubject<[SpaceRoomProxyProtocol], Never> = .init(configuration.initialSpaceRooms) let spaceRoomsSubject: CurrentValueSubject<[SpaceServiceRoomProtocol], Never> = .init(configuration.initialSpaceRooms)
id = configuration.spaceRoomProxy.id id = configuration.spaceServiceRoom.id
spaceRoomProxyPublisher = .init(configuration.spaceRoomProxy) spaceServiceRoomPublisher = .init(configuration.spaceServiceRoom)
spaceRoomsPublisher = spaceRoomsSubject.asCurrentValuePublisher() spaceRoomsPublisher = spaceRoomsSubject.asCurrentValuePublisher()
paginationStatePublisher = configuration.paginationStateSubject.asCurrentValuePublisher() paginationStatePublisher = configuration.paginationStateSubject.asCurrentValuePublisher()
@@ -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))
}
}
@@ -13,8 +13,8 @@ import MatrixRustSDKMocks
extension SpaceServiceProxyMock { extension SpaceServiceProxyMock {
struct Configuration { struct Configuration {
var topLevelSpaces: [SpaceRoomProxyProtocol] = [] var topLevelSpaces: [SpaceServiceRoomProtocol] = []
var joinedParentSpaces: [SpaceRoomProxyProtocol] = [] var joinedParentSpaces: [SpaceServiceRoomProtocol] = []
var spaceRoomLists: [String: SpaceRoomListProxyMock] = [:] var spaceRoomLists: [String: SpaceRoomListProxyMock] = [:]
var leaveSpaceRooms: [LeaveSpaceRoom] = [] var leaveSpaceRooms: [LeaveSpaceRoom] = []
} }
@@ -43,11 +43,11 @@ extension SpaceServiceProxyMock {
extension SpaceServiceProxyMock.Configuration { extension SpaceServiceProxyMock.Configuration {
static var populated: SpaceServiceProxyMock.Configuration { static var populated: SpaceServiceProxyMock.Configuration {
let spaceRoomLists = [SpaceRoomProxyProtocol].mockJoinedSpaces.map { let spaceRoomLists = [SpaceServiceRoomProtocol].mockJoinedSpaces.map {
($0.id, SpaceRoomListProxyMock(.init(spaceRoomProxy: $0, initialSpaceRooms: .mockSpaceList))) ($0.id, SpaceRoomListProxyMock(.init(spaceServiceRoom: $0, initialSpaceRooms: .mockSpaceList)))
} }
let subSpaceRoomLists = [SpaceRoomProxyProtocol].mockSpaceList.map { let subSpaceRoomLists = [SpaceServiceRoomProtocol].mockSpaceList.map {
($0.id, SpaceRoomListProxyMock(.init(spaceRoomProxy: $0, initialSpaceRooms: .mockSingleRoom))) ($0.id, SpaceRoomListProxyMock(.init(spaceServiceRoom: $0, initialSpaceRooms: .mockSingleRoom)))
} }
return .init(topLevelSpaces: .mockJoinedSpaces, spaceRoomLists: .init(uniqueKeysWithValues: spaceRoomLists + subSpaceRoomLists)) return .init(topLevelSpaces: .mockJoinedSpaces, spaceRoomLists: .init(uniqueKeysWithValues: spaceRoomLists + subSpaceRoomLists))
@@ -18,14 +18,14 @@ struct JoinRoomScreenCoordinatorParameters {
enum JoinRoomScreenSource { enum JoinRoomScreenSource {
case generic(roomID: String, via: [String]) case generic(roomID: String, via: [String])
case space(SpaceRoomProxyProtocol) case space(SpaceServiceRoomProtocol)
func roomIDAndVia() -> (roomID: String, via: [String]) { func roomIDAndVia() -> (roomID: String, via: [String]) {
switch self { switch self {
case let .generic(roomID: roomID, via: via): case let .generic(roomID: roomID, via: via):
return (roomID: roomID, via: via) return (roomID: roomID, via: via)
case let .space(spaceRoomProxy): case let .space(spaceServiceRoom):
return (roomID: spaceRoomProxy.id, via: spaceRoomProxy.via) return (roomID: spaceServiceRoom.id, via: spaceServiceRoom.via)
} }
} }
} }
@@ -49,7 +49,7 @@ struct JoinRoomScreenRoomDetails {
let isSpace: Bool? let isSpace: Bool?
let childrenCount: Int? let childrenCount: Int?
let spaceVisibility: SpaceRoomProxyVisibility? let spaceVisibility: SpaceServiceRoomVisibility?
} }
struct JoinRoomScreenViewState: BindableState { struct JoinRoomScreenViewState: BindableState {
@@ -172,8 +172,8 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
switch source { switch source {
case .generic(let roomID, _): case .generic(let roomID, _):
await updateGenericRoomDetails(roomID: roomID, roomInfo: roomInfo, inviter: inviter) await updateGenericRoomDetails(roomID: roomID, roomInfo: roomInfo, inviter: inviter)
case .space(let spaceRoomProxy): case .space(let spaceServiceRoom):
await updateSpaceRoomDetails(spaceRoomProxy: spaceRoomProxy, inviter: inviter) await updateSpaceRoomDetails(spaceServiceRoom: spaceServiceRoom, inviter: inviter)
} }
await updateMode() await updateMode()
} }
@@ -200,18 +200,18 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
spaceVisibility: nil) spaceVisibility: nil)
} }
private func updateSpaceRoomDetails(spaceRoomProxy: SpaceRoomProxyProtocol, inviter: RoomInviterDetails?) async { private func updateSpaceRoomDetails(spaceServiceRoom: SpaceServiceRoomProtocol, inviter: RoomInviterDetails?) async {
state.roomDetails = JoinRoomScreenRoomDetails(name: spaceRoomProxy.name, state.roomDetails = JoinRoomScreenRoomDetails(name: spaceServiceRoom.name,
topic: spaceRoomProxy.topic, topic: spaceServiceRoom.topic,
canonicalAlias: spaceRoomProxy.canonicalAlias, canonicalAlias: spaceServiceRoom.canonicalAlias,
avatar: spaceRoomProxy.avatar, avatar: spaceServiceRoom.avatar,
memberCount: spaceRoomProxy.joinedMembersCount, memberCount: spaceServiceRoom.joinedMembersCount,
heroes: spaceRoomProxy.heroes, heroes: spaceServiceRoom.heroes,
inviter: inviter, inviter: inviter,
isDirect: spaceRoomProxy.isDirect, isDirect: spaceServiceRoom.isDirect,
isSpace: spaceRoomProxy.isSpace, isSpace: spaceServiceRoom.isSpace,
childrenCount: spaceRoomProxy.childrenCount, childrenCount: spaceServiceRoom.childrenCount,
spaceVisibility: spaceRoomProxy.visibility) spaceVisibility: spaceServiceRoom.visibility)
} }
private func updateMode() async { private func updateMode() async {
@@ -225,16 +225,16 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo
return return
} }
if case .space(let spaceRoomProxy) = source { if case .space(let spaceServiceRoom) = source {
switch spaceRoomProxy.state { switch spaceServiceRoom.state {
case .invited: case .invited:
state.mode = .invited(isDM: spaceRoomProxy.isDirect == true && spaceRoomProxy.joinedMembersCount == 1) state.mode = .invited(isDM: spaceServiceRoom.isDirect == true && spaceServiceRoom.joinedMembersCount == 1)
case .knocked: case .knocked:
state.mode = .knocked state.mode = .knocked
case .banned: case .banned:
state.mode = .banned(sender: nil, reason: nil) state.mode = .banned(sender: nil, reason: nil)
default: default:
switch spaceRoomProxy.joinRule { switch spaceServiceRoom.joinRule {
case .private, .invite: case .private, .invite:
state.mode = .inviteRequired state.mode = .inviteRequired
case .knock, .knockRestricted: case .knock, .knockRestricted:
@@ -445,7 +445,7 @@ struct JoinRoomScreenPreviewWrapper: Identifiable {
} }
let source: JoinRoomScreenSource = if isSpace { let source: JoinRoomScreenSource = if isSpace {
.space(SpaceRoomProxyMock(mode: mode)) .space(SpaceServiceRoomMock(mode: mode))
} else { } else {
.generic(roomID: "1", via: []) .generic(roomID: "1", via: [])
} }
@@ -37,7 +37,7 @@ enum ManageAuthorizedSpacesScreenViewAction {
} }
struct AuthorizedSpacesSelection { struct AuthorizedSpacesSelection {
let joinedSpaces: [SpaceRoomProxyProtocol] let joinedSpaces: [SpaceServiceRoomProtocol]
let unknownSpacesIDs: [String] let unknownSpacesIDs: [String]
let initialSelectedIDs: Set<String> let initialSelectedIDs: Set<String>
let selectedIDs: PassthroughSubject<Set<String>, Never> = .init() let selectedIDs: PassthroughSubject<Set<String>, Never> = .init()
@@ -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, RoomAvatarImage(avatar: space.avatar,
avatarSize: .room(on: .authorizedSpaces), avatarSize: .room(on: .authorizedSpaces),
mediaProvider: context.mediaProvider) mediaProvider: context.mediaProvider)
@@ -32,7 +32,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
var canEditHistoryVisibility = false var canEditHistoryVisibility = false
/// The union of joined parent spaces and the joined spaces in the current access type /// 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 /// 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 { var selectableSpacesCount: Int {
@@ -118,7 +118,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
enum SpaceSelection { enum SpaceSelection {
/// There is only one available parent space for selection and is joined by the user /// 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 /// There is only one available space for selection and is unknown to the user
case singleUnknown(id: String) case singleUnknown(id: String)
/// Multiple spaces are available for selection /// Multiple spaces are available for selection
@@ -305,7 +305,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
} }
private func setupSelectableJoinedSpaces() async { private func setupSelectableJoinedSpaces() async {
var joinedParentSpaces: [SpaceRoomProxyProtocol] = [] var joinedParentSpaces: [SpaceServiceRoomProtocol] = []
switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) { switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) {
case .success(let value): case .success(let value):
joinedParentSpaces = value joinedParentSpaces = value
@@ -313,7 +313,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
break break
} }
var nonParentJoinedSpaces: [SpaceRoomProxyProtocol] = [] var nonParentJoinedSpaces: [SpaceServiceRoomProtocol] = []
for spaceID in state.currentSettings.accessType.spaceIDs where !joinedParentSpaces.contains(where: { $0.id == spaceID }) { 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) { if case let .success(.some(space)) = await clientProxy.spaceService.spaceForIdentifier(spaceID: spaceID) {
nonParentJoinedSpaces.append(space) nonParentJoinedSpaces.append(space)
@@ -269,7 +269,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
AppSettings.resetAllSettings() AppSettings.resetAllSettings()
let appSettings = AppSettings() let appSettings = AppSettings()
appSettings.spaceSettingsEnabled = true appSettings.spaceSettingsEnabled = true
let space = [SpaceRoomProxyProtocol].mockSingleRoom[0] let space = [SpaceServiceRoomProtocol].mockSingleRoom[0]
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
canonicalAlias: "#room:matrix.org", canonicalAlias: "#room:matrix.org",
@@ -286,7 +286,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
AppSettings.resetAllSettings() AppSettings.resetAllSettings()
let appSettings = AppSettings() let appSettings = AppSettings()
appSettings.spaceSettingsEnabled = true appSettings.spaceSettingsEnabled = true
let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
canonicalAlias: "#room:matrix.org", canonicalAlias: "#room:matrix.org",
@@ -319,7 +319,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
let appSettings = AppSettings() let appSettings = AppSettings()
appSettings.spaceSettingsEnabled = true appSettings.spaceSettingsEnabled = true
appSettings.knockingEnabled = true appSettings.knockingEnabled = true
let space = [SpaceRoomProxyProtocol].mockSingleRoom[0] let space = [SpaceServiceRoomProtocol].mockSingleRoom[0]
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
canonicalAlias: "#room:matrix.org", canonicalAlias: "#room:matrix.org",
@@ -337,7 +337,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
let appSettings = AppSettings() let appSettings = AppSettings()
appSettings.spaceSettingsEnabled = true appSettings.spaceSettingsEnabled = true
appSettings.knockingEnabled = true appSettings.knockingEnabled = true
let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
canonicalAlias: "#room:matrix.org", canonicalAlias: "#room:matrix.org",
@@ -10,36 +10,36 @@ import Compound
import SwiftUI import SwiftUI
struct SpaceHeaderView: View { struct SpaceHeaderView: View {
let spaceRoomProxy: SpaceRoomProxyProtocol let spaceServiceRoom: SpaceServiceRoomProtocol
let mediaProvider: MediaProviderProtocol? let mediaProvider: MediaProviderProtocol?
@State private var isPresentingTopic = false @State private var isPresentingTopic = false
var body: some View { var body: some View {
VStack(spacing: 16) { VStack(spacing: 16) {
RoomAvatarImage(avatar: spaceRoomProxy.avatar, RoomAvatarImage(avatar: spaceServiceRoom.avatar,
avatarSize: .room(on: .spaceHeader), avatarSize: .room(on: .spaceHeader),
mediaProvider: mediaProvider) mediaProvider: mediaProvider)
.accessibilityHidden(true) .accessibilityHidden(true)
VStack(spacing: 8) { VStack(spacing: 8) {
Text(spaceRoomProxy.name) Text(spaceServiceRoom.name)
.font(.compound.headingLGBold) .font(.compound.headingLGBold)
.foregroundStyle(.compound.textPrimary) .foregroundStyle(.compound.textPrimary)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
if let alias = spaceRoomProxy.canonicalAlias { if let alias = spaceServiceRoom.canonicalAlias {
CopyTextButton(content: alias) CopyTextButton(content: alias)
} }
spaceDetails spaceDetails
JoinedMembersBadgeView(heroes: spaceRoomProxy.heroes, JoinedMembersBadgeView(heroes: spaceServiceRoom.heroes,
joinedCount: spaceRoomProxy.joinedMembersCount, joinedCount: spaceServiceRoom.joinedMembersCount,
mediaProvider: mediaProvider) mediaProvider: mediaProvider)
} }
if let topic = spaceRoomProxy.topic { if let topic = spaceServiceRoom.topic {
Button { isPresentingTopic = true } label: { Button { isPresentingTopic = true } label: {
Text(topic) Text(topic)
.font(.compound.bodyMD) .font(.compound.bodyMD)
@@ -60,7 +60,7 @@ struct SpaceHeaderView: View {
.frame(height: 1 / UIScreen.main.scale) .frame(height: 1 / UIScreen.main.scale)
} }
.sheet(isPresented: $isPresentingTopic) { .sheet(isPresented: $isPresentingTopic) {
if let topic = spaceRoomProxy.topic { if let topic = spaceServiceRoom.topic {
SpaceHeaderTopicSheetView(topic: topic) SpaceHeaderTopicSheetView(topic: topic)
} }
} }
@@ -79,7 +79,7 @@ struct SpaceHeaderView: View {
} }
private var spaceDetailsVisibilityTitle: String { private var spaceDetailsVisibilityTitle: String {
switch spaceRoomProxy.visibility { switch spaceServiceRoom.visibility {
case .public: L10n.commonPublicSpace case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace case .private: L10n.commonPrivateSpace
case .restricted: L10n.commonSharedSpace case .restricted: L10n.commonSharedSpace
@@ -88,7 +88,7 @@ struct SpaceHeaderView: View {
} }
private var spaceDetailsVisibilityIcon: KeyPath<CompoundIcons, Image> { private var spaceDetailsVisibilityIcon: KeyPath<CompoundIcons, Image> {
switch spaceRoomProxy.visibility { switch spaceServiceRoom.visibility {
case .public: \.public case .public: \.public
case .private: \.lock case .private: \.lock
case .restricted: \.space case .restricted: \.space
@@ -107,41 +107,41 @@ struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
static var previews: some View { static var previews: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
ForEach(spaces, id: \.id) { space in 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", SpaceServiceRoomMock(.init(id: "!space1:matrix.org",
name: "Company Space", name: "Company Space",
isSpace: true, isSpace: true,
childrenCount: 10, childrenCount: 10,
joinedMembersCount: 50)), joinedMembersCount: 50)),
SpaceRoomProxyMock(.init(id: "!space2:matrix.org", SpaceServiceRoomMock(.init(id: "!space2:matrix.org",
name: "Community Space", name: "Community Space",
avatarURL: .mockMXCAvatar, avatarURL: .mockMXCAvatar,
isSpace: true, isSpace: true,
childrenCount: 20, childrenCount: 20,
joinedMembersCount: 78, joinedMembersCount: 78,
topic: "Description of the space goes right here.", topic: "Description of the space goes right here.",
canonicalAlias: "#space:matrix.org", canonicalAlias: "#space:matrix.org",
joinRule: .public)), joinRule: .public)),
SpaceRoomProxyMock(.init(id: "!space3:matrix.org", SpaceServiceRoomMock(.init(id: "!space3:matrix.org",
name: "Subspace", name: "Subspace",
isSpace: true, isSpace: true,
childrenCount: 30, childrenCount: 30,
joinedMembersCount: 123, joinedMembersCount: 123,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: ["Description of the space goes right here.", topic: ["Description of the space goes right here.",
"Lorem ipsum dolor sit amet consectetur.", "Lorem ipsum dolor sit amet consectetur.",
"Leo viverra morbi habitant in.", "Leo viverra morbi habitant in.",
"Sem amet enim habitant nibh augue mauris.", "Sem amet enim habitant nibh augue mauris.",
"Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.", "Interdum mauris ultrices tincidunt proin morbi erat aenean risus nibh.",
"Diam amet sit fermentum vulputate faucibus."].joined(separator: " "), "Diam amet sit fermentum vulputate faucibus."].joined(separator: " "),
canonicalAlias: "#subspace:matrix.org", canonicalAlias: "#subspace:matrix.org",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
] ]
} }
} }
@@ -13,32 +13,32 @@ import SwiftUI
struct SpaceRoomCell: View { struct SpaceRoomCell: View {
@Environment(\.dynamicTypeSize) var dynamicTypeSize @Environment(\.dynamicTypeSize) var dynamicTypeSize
let spaceRoomProxy: SpaceRoomProxyProtocol let spaceServiceRoom: SpaceServiceRoomProtocol
let isSelected: Bool let isSelected: Bool
var isJoining = false var isJoining = false
let mediaProvider: MediaProviderProtocol! let mediaProvider: MediaProviderProtocol!
enum Action { case select(SpaceRoomProxyProtocol), join(SpaceRoomProxyProtocol) } enum Action { case select(SpaceServiceRoomProtocol), join(SpaceServiceRoomProtocol) }
let action: (Action) -> Void let action: (Action) -> Void
private let verticalInsets = 12.0 private let verticalInsets = 12.0
private let horizontalInsets = 16.0 private let horizontalInsets = 16.0
private var subtitle: String { private var subtitle: String {
if spaceRoomProxy.isSpace { if spaceServiceRoom.isSpace {
switch spaceRoomProxy.visibility { switch spaceServiceRoom.visibility {
case .public: L10n.commonPublicSpace case .public: L10n.commonPublicSpace
case .private: L10n.commonPrivateSpace case .private: L10n.commonPrivateSpace
case .restricted: L10n.commonSharedSpace case .restricted: L10n.commonSharedSpace
case .none: L10n.commonPrivateSpace case .none: L10n.commonPrivateSpace
} }
} else { } else {
L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount) L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount)
} }
} }
var visibilityIcon: KeyPath<CompoundIcons, Image>? { var visibilityIcon: KeyPath<CompoundIcons, Image>? {
switch spaceRoomProxy.visibility { switch spaceServiceRoom.visibility {
case .public: \.public case .public: \.public
case .private: \.lockSolid case .private: \.lockSolid
case .restricted: nil case .restricted: nil
@@ -47,16 +47,16 @@ struct SpaceRoomCell: View {
} }
private var details: String { private var details: String {
if spaceRoomProxy.isSpace { if spaceServiceRoom.isSpace {
L10n.commonMemberCount(spaceRoomProxy.joinedMembersCount) L10n.commonMemberCount(spaceServiceRoom.joinedMembersCount)
} else { } 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 { var body: some View {
Button { Button {
action(.select(spaceRoomProxy)) action(.select(spaceServiceRoom))
} label: { } label: {
HStack(spacing: 16.0) { HStack(spacing: 16.0) {
avatar avatar
@@ -74,13 +74,13 @@ struct SpaceRoomCell: View {
.accessibilityElement(children: .combine) .accessibilityElement(children: .combine)
} }
.buttonStyle(SpaceRoomCellButtonStyle(isSelected: isSelected)) .buttonStyle(SpaceRoomCellButtonStyle(isSelected: isSelected))
.accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceRoomProxy.name)) .accessibilityIdentifier(A11yIdentifiers.spaceListScreen.spaceRoomName(spaceServiceRoom.name))
} }
@ViewBuilder @MainActor @ViewBuilder @MainActor
private var avatar: some View { private var avatar: some View {
if dynamicTypeSize < .accessibility3 { if dynamicTypeSize < .accessibility3 {
RoomAvatarImage(avatar: spaceRoomProxy.avatar, RoomAvatarImage(avatar: spaceServiceRoom.avatar,
avatarSize: .room(on: .spaces), avatarSize: .room(on: .spaces),
mediaProvider: mediaProvider) mediaProvider: mediaProvider)
.dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1)
@@ -91,7 +91,7 @@ struct SpaceRoomCell: View {
private var content: some View { private var content: some View {
HStack(spacing: 16) { HStack(spacing: 16) {
VStack(alignment: .leading, spacing: 2) { VStack(alignment: .leading, spacing: 2) {
Text(spaceRoomProxy.name) Text(spaceServiceRoom.name)
.font(.compound.bodyLGSemibold) .font(.compound.bodyLGSemibold)
.foregroundColor(.compound.textPrimary) .foregroundColor(.compound.textPrimary)
.lineLimit(1) .lineLimit(1)
@@ -128,9 +128,9 @@ struct SpaceRoomCell: View {
@ViewBuilder @ViewBuilder
private var accessory: some View { private var accessory: some View {
switch spaceRoomProxy.state { switch spaceServiceRoom.state {
case .none, .left, .invited: case .none, .left, .invited:
Button(L10n.actionJoin) { action(.join(spaceRoomProxy)) } Button(L10n.actionJoin) { action(.join(spaceServiceRoom)) }
.font(.compound.bodyLG) .font(.compound.bodyLG)
.foregroundStyle(.compound.textActionAccent) .foregroundStyle(.compound.textActionAccent)
.opacity(isJoining ? 0 : 1) .opacity(isJoining ? 0 : 1)
@@ -159,21 +159,21 @@ struct SpaceRoomCellButtonStyle: ButtonStyle {
struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview { struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview {
static let mediaProvider = MediaProviderMock(configuration: .init()) static let mediaProvider = MediaProviderMock(configuration: .init())
static let spaces = [SpaceRoomProxyProtocol].mockSpaceList static let spaces = [SpaceServiceRoomProtocol].mockSpaceList
static var previews: some View { static var previews: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
ForEach(spaces, id: \.id) { space in ForEach(spaces, id: \.id) { space in
SpaceRoomCell(spaceRoomProxy: space, SpaceRoomCell(spaceServiceRoom: space,
isSelected: false, isSelected: false,
mediaProvider: mediaProvider) { _ in } 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, isSelected: false,
isJoining: true, isJoining: true,
mediaProvider: mediaProvider) { _ in } 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, isSelected: false,
isJoining: true, isJoining: true,
mediaProvider: mediaProvider) { _ in } mediaProvider: mediaProvider) { _ in }
@@ -19,13 +19,13 @@ struct LeaveSpaceRoomDetailsCell: View {
let action: () -> Void let action: () -> Void
private var subtitle: String? { private var subtitle: String? {
guard !room.spaceRoomProxy.isSpace else { return nil } guard !room.spaceServiceRoom.isSpace else { return nil }
let memberCount = L10n.commonMemberCount(room.spaceRoomProxy.joinedMembersCount) let memberCount = L10n.commonMemberCount(room.spaceServiceRoom.joinedMembersCount)
return room.isLastAdmin ? L10n.screenLeaveSpaceLastAdminInfo(memberCount) : memberCount return room.isLastAdmin ? L10n.screenLeaveSpaceLastAdminInfo(memberCount) : memberCount
} }
var visibilityIcon: KeyPath<CompoundIcons, Image>? { var visibilityIcon: KeyPath<CompoundIcons, Image>? {
switch room.spaceRoomProxy.visibility { switch room.spaceServiceRoom.visibility {
case .public: \.public case .public: \.public
case .private: \.lockSolid case .private: \.lockSolid
case .restricted: nil case .restricted: nil
@@ -37,13 +37,13 @@ struct LeaveSpaceRoomDetailsCell: View {
Button(action: action) { Button(action: action) {
HStack(spacing: 16) { HStack(spacing: 16) {
if dynamicTypeSize < .accessibility3 { if dynamicTypeSize < .accessibility3 {
RoomAvatarImage(avatar: room.spaceRoomProxy.avatar, RoomAvatarImage(avatar: room.spaceServiceRoom.avatar,
avatarSize: .room(on: .leaveSpace), avatarSize: .room(on: .leaveSpace),
mediaProvider: mediaProvider) mediaProvider: mediaProvider)
} }
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
Text(room.spaceRoomProxy.name) Text(room.spaceServiceRoom.name)
.font(.compound.bodyLGSemibold) .font(.compound.bodyLGSemibold)
.foregroundStyle(.compound.textPrimary) .foregroundStyle(.compound.textPrimary)
.lineLimit(1) .lineLimit(1)
@@ -91,40 +91,40 @@ struct LeaveSpaceRoomDetailsCell: View {
struct LeaveSpaceRoomDetailsCell_Previews: PreviewProvider, TestablePreview { struct LeaveSpaceRoomDetailsCell_Previews: PreviewProvider, TestablePreview {
static var previews: some View { static var previews: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "1", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "1",
name: "Space", name: "Space",
isSpace: true)), isSpace: true)),
isLastAdmin: false, isLastAdmin: false,
isSelected: true), isSelected: true),
mediaProvider: MediaProviderMock(configuration: .init())) { } mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2",
name: "My Space", name: "My Space",
isSpace: true)), isSpace: true)),
isLastAdmin: true, isLastAdmin: true,
isSelected: false), isSelected: false),
mediaProvider: MediaProviderMock(configuration: .init())) { } mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "2", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "2",
name: "My Space", name: "My Space",
isSpace: true)), isSpace: true)),
isLastAdmin: true, isLastAdmin: true,
isSelected: false), isSelected: false),
hideSelection: true, hideSelection: true,
mediaProvider: MediaProviderMock(configuration: .init())) { } mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "3", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "3",
name: "Room", name: "Room",
isSpace: false)), isSpace: false)),
isLastAdmin: false, isLastAdmin: false,
isSelected: true), isSelected: true),
mediaProvider: MediaProviderMock(configuration: .init())) { } mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4",
name: "My Room", name: "My Room",
isSpace: false)), isSpace: false)),
isLastAdmin: true, isLastAdmin: true,
isSelected: false), isSelected: false),
mediaProvider: MediaProviderMock(configuration: .init())) { } mediaProvider: MediaProviderMock(configuration: .init())) { }
LeaveSpaceRoomDetailsCell(room: .init(spaceRoomProxy: SpaceRoomProxyMock(.init(id: "4", LeaveSpaceRoomDetailsCell(room: .init(spaceServiceRoom: SpaceServiceRoomMock(.init(id: "4",
name: "My Room", name: "My Room",
isSpace: false)), isSpace: false)),
isLastAdmin: true, isLastAdmin: true,
isSelected: false), isSelected: false),
hideSelection: true, hideSelection: true,
@@ -64,11 +64,11 @@ struct LeaveSpaceView: View {
context.viewState.leaveHandle.canLeave { context.viewState.leaveHandle.canLeave {
LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) { LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) {
Section { Section {
ForEach(context.viewState.leaveHandle.rooms, id: \.spaceRoomProxy.id) { room in ForEach(context.viewState.leaveHandle.rooms, id: \.spaceServiceRoom.id) { room in
LeaveSpaceRoomDetailsCell(room: room, LeaveSpaceRoomDetailsCell(room: room,
hideSelection: context.viewState.leaveHandle.mode == .onlyAdminRooms, hideSelection: context.viewState.leaveHandle.mode == .onlyAdminRooms,
mediaProvider: context.mediaProvider) { mediaProvider: context.mediaProvider) {
context.send(viewAction: .toggleRoom(roomID: room.spaceRoomProxy.id)) context.send(viewAction: .toggleRoom(roomID: room.spaceServiceRoom.id))
} }
.disabled(room.isLastAdmin) .disabled(room.isLastAdmin)
} }
@@ -136,27 +136,27 @@ struct LeaveSpaceView_Previews: PreviewProvider, TestablePreview {
.previewDisplayName("Last Space Admin") .previewDisplayName("Last Space Admin")
} }
static let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org", static let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team", name: "Engineering Team",
isSpace: true, isSpace: true,
childrenCount: 30, childrenCount: 30,
joinedMembersCount: 76, joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel { static func makeViewModel(mode: LeaveSpaceHandleProxy.Mode) -> LeaveSpaceViewModel {
let rooms: [LeaveSpaceRoom] = switch mode { let rooms: [LeaveSpaceRoom] = switch mode {
case .manyRooms: .mockRooms case .manyRooms: .mockRooms
case .onlyAdminRooms: .mockAdminRooms case .onlyAdminRooms: .mockAdminRooms
case .noRooms: .mockSingleSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: false) case .noRooms: .mockSingleSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: false)
case .lastSpaceAdmin: .mockRoomsWithSpace(spaceRoomProxy: spaceRoomProxy, isLastAdmin: true) case .lastSpaceAdmin: .mockRoomsWithSpace(spaceServiceRoom: spaceServiceRoom, isLastAdmin: true)
} }
let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceRoomProxy.id, let leaveHandle = LeaveSpaceHandleProxy(spaceID: spaceServiceRoom.id,
leaveHandle: LeaveSpaceHandleSDKMock(.init(rooms: rooms))) leaveHandle: LeaveSpaceHandleSDKMock(.init(rooms: rooms)))
return LeaveSpaceViewModel(spaceName: spaceRoomProxy.name, return LeaveSpaceViewModel(spaceName: spaceServiceRoom.name,
canEditRolesAndPermissions: true, canEditRolesAndPermissions: true,
leaveHandle: leaveHandle, leaveHandle: leaveHandle,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -18,7 +18,7 @@ struct SpaceListScreenViewState: BindableState {
var userDisplayName: String? var userDisplayName: String?
var userAvatarURL: URL? var userAvatarURL: URL?
var topLevelSpaces: [SpaceRoomProxyProtocol] var topLevelSpaces: [SpaceServiceRoomProtocol]
var selectedSpaceID: String? var selectedSpaceID: String?
var isCreateSpaceEnabled: Bool var isCreateSpaceEnabled: Bool
@@ -65,8 +65,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie
MXLog.info("View model: received view action: \(viewAction)") MXLog.info("View model: received view action: \(viewAction)")
switch viewAction { switch viewAction {
case .spaceAction(.select(let spaceRoomProxy)): case .spaceAction(.select(let spaceServiceRoom)):
Task { await selectSpace(spaceRoomProxy) } Task { await selectSpace(spaceServiceRoom) }
case .spaceAction(.join): case .spaceAction(.join):
fatalError("There shouldn't be any unjoined spaces in the joined spaces list.") fatalError("There shouldn't be any unjoined spaces in the joined spaces list.")
case .showSettings: case .showSettings:
@@ -86,8 +86,8 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie
// MARK: - Private // MARK: - Private
private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) { switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) {
case .success(let spaceRoomListProxy): case .success(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy)) actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .failure(let error): case .failure(let error):
@@ -85,9 +85,9 @@ struct SpaceListScreen: View {
} }
private var spaces: some View { private var spaces: some View {
ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceRoomProxy in ForEach(context.viewState.topLevelSpaces, id: \.id) { spaceServiceRoom in
SpaceRoomCell(spaceRoomProxy: spaceRoomProxy, SpaceRoomCell(spaceServiceRoom: spaceServiceRoom,
isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceID, isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceID,
mediaProvider: context.mediaProvider) { action in mediaProvider: context.mediaProvider) { action in
context.send(viewAction: .spaceAction(action)) context.send(viewAction: .spaceAction(action))
} }
@@ -22,7 +22,7 @@ struct SpaceScreenCoordinatorParameters {
enum SpaceScreenCoordinatorAction { enum SpaceScreenCoordinatorAction {
case selectSpace(SpaceRoomListProxyProtocol) case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol) case selectUnjoinedSpace(SpaceServiceRoomProtocol)
case selectRoom(roomID: String) case selectRoom(roomID: String)
case leftSpace case leftSpace
case displayMembers(roomProxy: JoinedRoomProxyProtocol) case displayMembers(roomProxy: JoinedRoomProxyProtocol)
@@ -60,8 +60,8 @@ final class SpaceScreenCoordinator: CoordinatorProtocol {
switch action { switch action {
case .selectSpace(let spaceRoomListProxy): case .selectSpace(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy)) actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .selectUnjoinedSpace(let spaceRoomProxy): case .selectUnjoinedSpace(let spaceServiceRoom):
actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy)) actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom))
case .selectRoom(let roomID): case .selectRoom(let roomID):
actionsSubject.send(.selectRoom(roomID: roomID)) actionsSubject.send(.selectRoom(roomID: roomID))
case .leftSpace: case .leftSpace:
@@ -10,7 +10,7 @@ import Foundation
enum SpaceScreenViewModelAction { enum SpaceScreenViewModelAction {
case selectSpace(SpaceRoomListProxyProtocol) case selectSpace(SpaceRoomListProxyProtocol)
case selectUnjoinedSpace(SpaceRoomProxyProtocol) case selectUnjoinedSpace(SpaceServiceRoomProtocol)
case selectRoom(roomID: String) case selectRoom(roomID: String)
case leftSpace case leftSpace
case presentRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol) case presentRolesAndPermissions(roomProxy: JoinedRoomProxyProtocol)
@@ -19,13 +19,13 @@ enum SpaceScreenViewModelAction {
} }
struct SpaceScreenViewState: BindableState { struct SpaceScreenViewState: BindableState {
var space: SpaceRoomProxyProtocol var space: SpaceServiceRoomProtocol
var permalink: URL? var permalink: URL?
var roomProxy: JoinedRoomProxyProtocol? var roomProxy: JoinedRoomProxyProtocol?
var isPaginating = false var isPaginating = false
var rooms: [SpaceRoomProxyProtocol] var rooms: [SpaceServiceRoomProtocol]
var selectedSpaceRoomID: String? var selectedSpaceRoomID: String?
var joiningRoomIDs: Set<String> = [] var joiningRoomIDs: Set<String> = []
@@ -37,12 +37,12 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.appSettings = appSettings self.appSettings = appSettings
super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceRoomProxyPublisher.value, super.init(initialViewState: SpaceScreenViewState(space: spaceRoomListProxy.spaceServiceRoomPublisher.value,
rooms: spaceRoomListProxy.spaceRoomsPublisher.value, rooms: spaceRoomListProxy.spaceRoomsPublisher.value,
selectedSpaceRoomID: selectedSpaceRoomPublisher.value), selectedSpaceRoomID: selectedSpaceRoomPublisher.value),
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
spaceRoomListProxy.spaceRoomProxyPublisher spaceRoomListProxy.spaceServiceRoomPublisher
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.weakAssign(to: \.state.space, on: self) .weakAssign(to: \.state.space, on: self)
.store(in: &cancellables) .store(in: &cancellables)
@@ -107,19 +107,19 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
MXLog.info("View model: received view action: \(viewAction)") MXLog.info("View model: received view action: \(viewAction)")
switch viewAction { switch viewAction {
case .spaceAction(.select(let spaceRoomProxy)): case .spaceAction(.select(let spaceServiceRoom)):
if spaceRoomProxy.isSpace { if spaceServiceRoom.isSpace {
if spaceRoomProxy.state != .joined { if spaceServiceRoom.state != .joined {
actionsSubject.send(.selectUnjoinedSpace(spaceRoomProxy)) actionsSubject.send(.selectUnjoinedSpace(spaceServiceRoom))
} else { } else {
Task { await selectSpace(spaceRoomProxy) } Task { await selectSpace(spaceServiceRoom) }
} }
} else { } else {
// No need to check the join state, the room flow will show an appropriately configured join screen if needed. // 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)): case .spaceAction(.join(let spaceServiceRoom)):
Task { await join(spaceRoomProxy) } Task { await join(spaceServiceRoom) }
case .leaveSpace: case .leaveSpace:
Task { await showLeaveSpaceConfirmation() } Task { await showLeaveSpaceConfirmation() }
case .displayMembers(let roomProxy): case .displayMembers(let roomProxy):
@@ -136,11 +136,11 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
// MARK: - Private // MARK: - Private
private func join(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { private func join(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
state.joiningRoomIDs.insert(spaceRoomProxy.id) state.joiningRoomIDs.insert(spaceServiceRoom.id)
defer { state.joiningRoomIDs.remove(spaceRoomProxy.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() showFailureIndicator()
return return
} }
@@ -148,8 +148,8 @@ class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtoc
// We don't want to show the space room after joining it this way 🤷‍♂️ // We don't want to show the space room after joining it this way 🤷‍♂️
} }
private func selectSpace(_ spaceRoomProxy: SpaceRoomProxyProtocol) async { private func selectSpace(_ spaceServiceRoom: SpaceServiceRoomProtocol) async {
switch await spaceServiceProxy.spaceRoomList(spaceID: spaceRoomProxy.id) { switch await spaceServiceProxy.spaceRoomList(spaceID: spaceServiceRoom.id) {
case .success(let spaceRoomListProxy): case .success(let spaceRoomListProxy):
actionsSubject.send(.selectSpace(spaceRoomListProxy)) actionsSubject.send(.selectSpace(spaceRoomListProxy))
case .failure(let error): case .failure(let error):
@@ -15,7 +15,7 @@ struct SpaceScreen: View {
var body: some View { var body: some View {
ScrollView { ScrollView {
LazyVStack(spacing: 0) { LazyVStack(spacing: 0) {
SpaceHeaderView(spaceRoomProxy: context.viewState.space, SpaceHeaderView(spaceServiceRoom: context.viewState.space,
mediaProvider: context.mediaProvider) mediaProvider: context.mediaProvider)
rooms rooms
} }
@@ -32,10 +32,10 @@ struct SpaceScreen: View {
@ViewBuilder @ViewBuilder
var rooms: some View { var rooms: some View {
ForEach(context.viewState.rooms, id: \.id) { spaceRoomProxy in ForEach(context.viewState.rooms, id: \.id) { spaceServiceRoom in
SpaceRoomCell(spaceRoomProxy: spaceRoomProxy, SpaceRoomCell(spaceServiceRoom: spaceServiceRoom,
isSelected: spaceRoomProxy.id == context.viewState.selectedSpaceRoomID, isSelected: spaceServiceRoom.id == context.viewState.selectedSpaceRoomID,
isJoining: context.viewState.joiningRoomIDs.contains(spaceRoomProxy.id), isJoining: context.viewState.joiningRoomIDs.contains(spaceServiceRoom.id),
mediaProvider: context.mediaProvider) { action in mediaProvider: context.mediaProvider) { action in
context.send(viewAction: .spaceAction(action)) context.send(viewAction: .spaceAction(action))
} }
@@ -114,16 +114,16 @@ struct SpaceScreen_Previews: PreviewProvider, TestablePreview {
} }
static func makeViewModel() -> SpaceScreenViewModel { static func makeViewModel() -> SpaceScreenViewModel {
let spaceRoomProxy = SpaceRoomProxyMock(.init(id: "!eng-space:matrix.org", let spaceServiceRoom = SpaceServiceRoomMock(.init(id: "!eng-space:matrix.org",
name: "Engineering Team", name: "Engineering Team",
isSpace: true, isSpace: true,
childrenCount: 30, childrenCount: 30,
joinedMembersCount: 76, joinedMembersCount: 76,
heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose], heroes: [.mockDan, .mockBob, .mockCharlie, .mockVerbose],
topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.", topic: "Description of the space goes right here. Lorem ipsum dolor sit amet consectetur. Leo viverra morbi habitant in.",
canonicalAlias: "#engineering-team:element.io", canonicalAlias: "#engineering-team:element.io",
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")]))) joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy, let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom,
initialSpaceRooms: .mockSpaceList)) initialSpaceRooms: .mockSpaceList))
let clientProxy = ClientProxyMock(.init()) let clientProxy = ClientProxyMock(.init())
@@ -35,7 +35,7 @@ final class LeaveSpaceHandleProxy {
room.spaceRoom.roomId != spaceID else { room.spaceRoom.roomId != spaceID else {
return nil return nil
} }
return .init(spaceRoomProxy: SpaceRoomProxy(spaceRoom: room.spaceRoom), return .init(spaceServiceRoom: SpaceServiceRoom(spaceRoom: room.spaceRoom),
isLastAdmin: room.isLastAdmin, isLastAdmin: room.isLastAdmin,
isSelected: !room.isLastAdmin) isSelected: !room.isLastAdmin)
} }
@@ -64,21 +64,21 @@ final class LeaveSpaceHandleProxy {
} }
func toggleRoom(roomID: String) { 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 return
} }
room.isSelected.toggle() room.isSelected.toggle()
} }
func leave() async -> Result<Void, SpaceServiceProxyError> { func leave() async -> Result<Void, SpaceServiceProxyError> {
let selectedRoomIDs = rooms.filter(\.isSelected).map(\.spaceRoomProxy.id) let selectedRoomIDs = rooms.filter(\.isSelected).map(\.spaceServiceRoom.id)
do { do {
return try await .success(leaveHandle.leave(roomIds: selectedRoomIDs + [id])) return try await .success(leaveHandle.leave(roomIds: selectedRoomIDs + [id]))
} catch { } catch {
MXLog.error("Failed leaving space \(id): \(error)") MXLog.error("Failed leaving space \(id): \(error)")
rooms = rooms.filter { leaveRoom in 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)) return .failure(.sdkError(error))
} }
@@ -86,12 +86,12 @@ final class LeaveSpaceHandleProxy {
} }
@Observable class LeaveSpaceRoomDetails { @Observable class LeaveSpaceRoomDetails {
let spaceRoomProxy: SpaceRoomProxyProtocol let spaceServiceRoom: SpaceServiceRoomProtocol
let isLastAdmin: Bool let isLastAdmin: Bool
var isSelected: Bool var isSelected: Bool
init(spaceRoomProxy: SpaceRoomProxyProtocol, isLastAdmin: Bool, isSelected: Bool) { init(spaceServiceRoom: SpaceServiceRoomProtocol, isLastAdmin: Bool, isSelected: Bool) {
self.spaceRoomProxy = spaceRoomProxy self.spaceServiceRoom = spaceServiceRoom
self.isLastAdmin = isLastAdmin self.isLastAdmin = isLastAdmin
self.isSelected = isSelected self.isSelected = isSelected
} }
@@ -10,19 +10,19 @@ import Combine
import MatrixRustSDK import MatrixRustSDK
class SpaceRoomListProxy: SpaceRoomListProxyProtocol { class SpaceRoomListProxy: SpaceRoomListProxyProtocol {
var id: String { spaceRoomProxyPublisher.value.id } var id: String { spaceServiceRoomPublisher.value.id }
private let spaceRoomList: SpaceRoomListProtocol private let spaceRoomList: SpaceRoomListProtocol
private var spaceRoomProxyHandle: TaskHandle? private var spaceServiceRoomHandle: TaskHandle?
private let spaceRoomProxySubject: CurrentValueSubject<SpaceRoomProxyProtocol, Never> private let spaceServiceRoomSubject: CurrentValueSubject<SpaceServiceRoomProtocol, Never>
var spaceRoomProxyPublisher: CurrentValuePublisher<SpaceRoomProxyProtocol, Never> { var spaceServiceRoomPublisher: CurrentValuePublisher<SpaceServiceRoomProtocol, Never> {
spaceRoomProxySubject.asCurrentValuePublisher() spaceServiceRoomSubject.asCurrentValuePublisher()
} }
private var spaceRoomsHandle: TaskHandle? private var spaceRoomsHandle: TaskHandle?
private let spaceRoomsSubject = CurrentValueSubject<[SpaceRoomProxyProtocol], Never>([]) private let spaceRoomsSubject = CurrentValueSubject<[SpaceServiceRoomProtocol], Never>([])
var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> {
spaceRoomsSubject.asCurrentValuePublisher() spaceRoomsSubject.asCurrentValuePublisher()
} }
@@ -33,7 +33,7 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol {
guard let spaceRoom = spaceRoomList.space() else { throw SpaceRoomListProxyError.missingSpace } guard let spaceRoom = spaceRoomList.space() else { throw SpaceRoomListProxyError.missingSpace }
self.spaceRoomList = spaceRoomList self.spaceRoomList = spaceRoomList
spaceRoomProxySubject = .init(SpaceRoomProxy(spaceRoom: spaceRoom)) spaceServiceRoomSubject = .init(SpaceServiceRoom(spaceRoom: spaceRoom))
let paginationStateSubject = CurrentValueSubject<SpaceRoomListPaginationState, Never>(spaceRoomList.paginationState()) let paginationStateSubject = CurrentValueSubject<SpaceRoomListPaginationState, Never>(spaceRoomList.paginationState())
paginationStatePublisher = paginationStateSubject.asCurrentValuePublisher() paginationStatePublisher = paginationStateSubject.asCurrentValuePublisher()
@@ -46,9 +46,9 @@ class SpaceRoomListProxy: SpaceRoomListProxyProtocol {
self?.handleUpdates(updates) 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 } 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 { for update in updates {
switch update { switch update {
case .append(let spaceRooms): case .append(let spaceRooms):
rooms.append(contentsOf: spaceRooms.map(SpaceRoomProxy.init)) rooms.append(contentsOf: spaceRooms.map(SpaceServiceRoom.init))
case .clear: case .clear:
rooms.removeAll() rooms.removeAll()
case .pushFront(let spaceRoom): case .pushFront(let spaceRoom):
rooms.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: 0) rooms.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: 0)
case .pushBack(let spaceRoom): case .pushBack(let spaceRoom):
rooms.append(SpaceRoomProxy(spaceRoom: spaceRoom)) rooms.append(SpaceServiceRoom(spaceRoom: spaceRoom))
case .popFront: case .popFront:
rooms.removeFirst() rooms.removeFirst()
case .popBack: case .popBack:
rooms.removeLast() rooms.removeLast()
case .insert(let index, let spaceRoom): 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): case .set(let index, let spaceRoom):
rooms[Int(index)] = SpaceRoomProxy(spaceRoom: spaceRoom) rooms[Int(index)] = SpaceServiceRoom(spaceRoom: spaceRoom)
case .remove(let index): case .remove(let index):
rooms.remove(at: Int(index)) rooms.remove(at: Int(index))
case .truncate(let length): case .truncate(let length):
rooms.removeSubrange(Int(length)..<rooms.count) rooms.removeSubrange(Int(length)..<rooms.count)
case .reset(let spaceRooms): case .reset(let spaceRooms):
rooms = spaceRooms.map(SpaceRoomProxy.init) rooms = spaceRooms.map(SpaceServiceRoom.init)
} }
} }
@@ -17,8 +17,8 @@ enum SpaceRoomListProxyError: Error {
protocol SpaceRoomListProxyProtocol { protocol SpaceRoomListProxyProtocol {
var id: String { get } var id: String { get }
var spaceRoomProxyPublisher: CurrentValuePublisher<SpaceRoomProxyProtocol, Never> { get } var spaceServiceRoomPublisher: CurrentValuePublisher<SpaceServiceRoomProtocol, Never> { get }
var spaceRoomsPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { get } var spaceRoomsPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get }
var paginationStatePublisher: CurrentValuePublisher<SpaceRoomListPaginationState, Never> { get } var paginationStatePublisher: CurrentValuePublisher<SpaceRoomListPaginationState, Never> { get }
func paginate() async func paginate() async
@@ -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 }
}
@@ -14,8 +14,8 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
private let spaceService: SpaceServiceProtocol private let spaceService: SpaceServiceProtocol
private var topLevelSpacesHandle: TaskHandle? private var topLevelSpacesHandle: TaskHandle?
private let spacesSubject = CurrentValueSubject<[SpaceRoomProxyProtocol], Never>([]) private let spacesSubject = CurrentValueSubject<[SpaceServiceRoomProtocol], Never>([])
var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> {
spacesSubject.asCurrentValuePublisher() spacesSubject.asCurrentValuePublisher()
} }
@@ -40,9 +40,9 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
} }
} }
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError> { func spaceForIdentifier(spaceID: String) async -> Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError> {
do { do {
return try await .success(spaceService.getSpaceRoom(roomId: spaceID).map(SpaceRoomProxy.init)) return try await .success(spaceService.getSpaceRoom(roomId: spaceID).map(SpaceServiceRoom.init))
} catch { } catch {
MXLog.error("Failed getting space room for \(spaceID): \(error)") MXLog.error("Failed getting space room for \(spaceID): \(error)")
return .failure(.sdkError(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 { do {
return try await .success(spaceService.joinedParentsOfChild(childId: childID).map(SpaceRoomProxy.init)) return try await .success(spaceService.joinedParentsOfChild(childId: childID).map(SpaceServiceRoom.init))
} catch { } catch {
MXLog.error("Failed to get joined parents for \(childID): \(error)") MXLog.error("Failed to get joined parents for \(childID): \(error)")
return .failure(.sdkError(error)) return .failure(.sdkError(error))
@@ -75,27 +75,27 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
for update in updates { for update in updates {
switch update { switch update {
case .append(let spaceRooms): case .append(let spaceRooms):
spaces.append(contentsOf: spaceRooms.map(SpaceRoomProxy.init)) spaces.append(contentsOf: spaceRooms.map(SpaceServiceRoom.init))
case .clear: case .clear:
spaces.removeAll() spaces.removeAll()
case .pushFront(let spaceRoom): case .pushFront(let spaceRoom):
spaces.insert(SpaceRoomProxy(spaceRoom: spaceRoom), at: 0) spaces.insert(SpaceServiceRoom(spaceRoom: spaceRoom), at: 0)
case .pushBack(let spaceRoom): case .pushBack(let spaceRoom):
spaces.append(SpaceRoomProxy(spaceRoom: spaceRoom)) spaces.append(SpaceServiceRoom(spaceRoom: spaceRoom))
case .popFront: case .popFront:
spaces.removeFirst() spaces.removeFirst()
case .popBack: case .popBack:
spaces.removeLast() spaces.removeLast()
case .insert(let index, let spaceRoom): 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): case .set(let index, let spaceRoom):
spaces[Int(index)] = SpaceRoomProxy(spaceRoom: spaceRoom) spaces[Int(index)] = SpaceServiceRoom(spaceRoom: spaceRoom)
case .remove(let index): case .remove(let index):
spaces.remove(at: Int(index)) spaces.remove(at: Int(index))
case .truncate(let length): case .truncate(let length):
spaces.removeSubrange(Int(length)..<spaces.count) spaces.removeSubrange(Int(length)..<spaces.count)
case .reset(let spaceRooms): case .reset(let spaceRooms):
spaces = spaceRooms.map(SpaceRoomProxy.init) spaces = spaceRooms.map(SpaceServiceRoom.init)
} }
} }
@@ -15,12 +15,12 @@ enum SpaceServiceProxyError: Error {
// sourcery: AutoMockable // sourcery: AutoMockable
protocol SpaceServiceProxyProtocol { protocol SpaceServiceProxyProtocol {
var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { get } var topLevelSpacesPublisher: CurrentValuePublisher<[SpaceServiceRoomProtocol], Never> { get }
func spaceRoomList(spaceID: String) async -> Result<SpaceRoomListProxyProtocol, SpaceServiceProxyError> func spaceRoomList(spaceID: String) async -> Result<SpaceRoomListProxyProtocol, SpaceServiceProxyError>
/// Returns a joined space given its identifier /// Returns a joined space given its identifier
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError> func spaceForIdentifier(spaceID: String) async -> Result<SpaceServiceRoomProtocol?, SpaceServiceProxyError>
func leaveSpace(spaceID: String) async -> Result<LeaveSpaceHandleProxy, SpaceServiceProxyError> func leaveSpace(spaceID: String) async -> Result<LeaveSpaceHandleProxy, SpaceServiceProxyError>
/// Returns all the parent spaces of a child that user has joined. /// 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>
} }
@@ -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
}
}
@@ -9,7 +9,7 @@
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
enum SpaceRoomProxyVisibility: Equatable { enum SpaceServiceRoomVisibility: Equatable {
case `public` case `public`
case `private` case `private`
case restricted case restricted
@@ -17,7 +17,7 @@ enum SpaceRoomProxyVisibility: Equatable {
} }
// sourcery: AutoMockable // sourcery: AutoMockable
protocol SpaceRoomProxyProtocol { protocol SpaceServiceRoomProtocol {
var id: String { get } var id: String { get }
var name: String { get } var name: String { get }
var rawName: String? { get } var rawName: String? { get }
@@ -39,7 +39,7 @@ protocol SpaceRoomProxyProtocol {
var via: [String] { get } var via: [String] { get }
} }
extension SpaceRoomProxyProtocol { extension SpaceServiceRoomProtocol {
var avatar: RoomAvatar { var avatar: RoomAvatar {
if isSpace { if isSpace {
.space(id: id, name: name, avatarURL: avatarURL) .space(id: id, name: name, avatarURL: avatarURL)
@@ -50,7 +50,7 @@ extension SpaceRoomProxyProtocol {
} }
} }
var visibility: SpaceRoomProxyVisibility? { var visibility: SpaceServiceRoomVisibility? {
switch joinRule { switch joinRule {
case .public: case .public:
.public .public
@@ -597,7 +597,7 @@ class MockScreen: Identifiable {
deviceID: "MOCKCLIENT", deviceID: "MOCKCLIENT",
roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))), roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(roomSummaries))),
spaceServiceConfiguration: .init(topLevelSpaces: .mockSingleRoom), 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. // 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()) let spaceServiceProxy = SpaceServiceProxyMock(id == .userSessionSpacesFlow ? .populated : .init())
@@ -311,7 +311,7 @@ class HomeScreenViewModelTests: XCTestCase {
XCTAssertEqual(invitedRoomIDs.count, 2) XCTAssertEqual(invitedRoomIDs.count, 2)
let deferred = deferFulfillment(viewModel.actions) { 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])) context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0]))
try await deferred.fulfill() try await deferred.fulfill()
@@ -408,7 +408,7 @@ class HomeScreenViewModelTests: XCTestCase {
let spaceServiceProxy = SpaceServiceProxyMock(.init()) let spaceServiceProxy = SpaceServiceProxyMock(.init())
spaceServiceProxy.spaceRoomListSpaceIDClosure = { spaceID in 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 clientProxy.underlyingSpaceService = spaceServiceProxy
case nil: case nil:
@@ -29,7 +29,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testSetSingleJoinedSpaceMembersAccess() async throws { func testSetSingleJoinedSpaceMembersAccess() async throws {
let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom
let space = singleRoom[0] let space = singleRoom[0]
setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public) setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public)
@@ -60,7 +60,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testSetSingleJoinedAskToJoinWithSpaceMembersAccess() async throws { func testSetSingleJoinedAskToJoinWithSpaceMembersAccess() async throws {
let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom
let space = singleRoom[0] let space = singleRoom[0]
setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public) setupViewModel(joinedParentSpaces: singleRoom, joinRule: .public)
@@ -91,7 +91,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws { func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws {
let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom
let space = singleRoom[0] let space = singleRoom[0]
setupViewModel(joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomId: space.id)])) setupViewModel(joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomId: space.id)]))
@@ -122,7 +122,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testMultipleKnownSpacesMembersSelection() async throws { func testMultipleKnownSpacesMembersSelection() async throws {
let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
setupViewModel(joinedParentSpaces: spaces, joinRule: .public) setupViewModel(joinedParentSpaces: spaces, joinRule: .public)
let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 } let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 }
@@ -166,7 +166,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testMultipleKnownAskToJoinSpacesMembersSelection() async throws { func testMultipleKnownAskToJoinSpacesMembersSelection() async throws {
let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
setupViewModel(joinedParentSpaces: spaces, joinRule: .public) setupViewModel(joinedParentSpaces: spaces, joinRule: .public)
let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 } let deferred = deferFulfillment(context.$viewState) { $0.selectableJoinedSpaces.count == 3 }
@@ -210,7 +210,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testMultipleSpacesMembersSelection() async throws { func testMultipleSpacesMembersSelection() async throws {
let spaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
setupViewModel(joinedParentSpaces: spaces, setupViewModel(joinedParentSpaces: spaces,
joinRule: .restricted(rules: [.roomMembership(roomId: "unknownSpaceID")])) joinRule: .restricted(rules: [.roomMembership(roomId: "unknownSpaceID")]))
@@ -256,8 +256,8 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
} }
func testMultipleSpacesMembersSelectionWithAnExistingNonParentButJoinedSpace() async throws { func testMultipleSpacesMembersSelectionWithAnExistingNonParentButJoinedSpace() async throws {
let joinedParentSpaces = [SpaceRoomProxyProtocol].mockJoinedSpaces2 let joinedParentSpaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom
let space = singleRoom[0] let space = singleRoom[0]
let allSpaces = joinedParentSpaces + singleRoom let allSpaces = joinedParentSpaces + singleRoom
setupViewModel(joinedParentSpaces: joinedParentSpaces, setupViewModel(joinedParentSpaces: joinedParentSpaces,
@@ -319,7 +319,7 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
func testEmptySpaceMembersSelectionWithJoinedParentEdgeCase() async throws { func testEmptySpaceMembersSelectionWithJoinedParentEdgeCase() async throws {
// Edge case where there is one available joined parent but the room has a restricted join rule. // Edge case where there is one available joined parent but the room has a restricted join rule.
// With no space ids in it // With no space ids in it
let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom let singleRoom = [SpaceServiceRoomProtocol].mockSingleRoom
setupViewModel(joinedParentSpaces: singleRoom, setupViewModel(joinedParentSpaces: singleRoom,
joinRule: .restricted(rules: [])) joinRule: .restricted(rules: []))
@@ -424,8 +424,8 @@ class SecurityAndPrivacyScreenViewModelTests: XCTestCase {
// MARK: - Helpers // MARK: - Helpers
private func setupViewModel(joinedParentSpaces: [SpaceRoomProxyProtocol], private func setupViewModel(joinedParentSpaces: [SpaceServiceRoomProtocol],
topLevelSpaces: [SpaceRoomProxyProtocol] = [], topLevelSpaces: [SpaceServiceRoomProtocol] = [],
joinRule: JoinRule) { joinRule: JoinRule) {
let appSettings = AppSettings() let appSettings = AppSettings()
appSettings.spaceSettingsEnabled = true appSettings.spaceSettingsEnabled = true
@@ -13,7 +13,7 @@ import XCTest
@MainActor @MainActor
class SpaceListScreenViewModelTests: XCTestCase { class SpaceListScreenViewModelTests: XCTestCase {
var topLevelSpacesSubject: CurrentValueSubject<[SpaceRoomProxyProtocol], Never>! var topLevelSpacesSubject: CurrentValueSubject<[SpaceServiceRoomProtocol], Never>!
var spaceServiceProxy: SpaceServiceProxyMock! var spaceServiceProxy: SpaceServiceProxyMock!
var appSettings: AppSettings! var appSettings: AppSettings!
@@ -47,7 +47,7 @@ class SpaceListScreenViewModelTests: XCTestCase {
deferred = deferFulfillment(context.observe(\.viewState.topLevelSpaces)) { $0.count == 1 } deferred = deferFulfillment(context.observe(\.viewState.topLevelSpaces)) { $0.count == 1 }
topLevelSpacesSubject.send([ topLevelSpacesSubject.send([
SpaceRoomProxyMock(.init(isSpace: true)) SpaceServiceRoomMock(.init(isSpace: true))
]) ])
try await deferred.fulfill() try await deferred.fulfill()
XCTAssertEqual(context.viewState.topLevelSpaces.count, 1) XCTAssertEqual(context.viewState.topLevelSpaces.count, 1)
@@ -97,15 +97,15 @@ class SpaceListScreenViewModelTests: XCTestCase {
let userSession = UserSessionMock(.init(clientProxy: clientProxy)) let userSession = UserSessionMock(.init(clientProxy: clientProxy))
topLevelSpacesSubject = .init([ topLevelSpacesSubject = .init([
SpaceRoomProxyMock(.init(id: "space1", isSpace: true)), SpaceServiceRoomMock(.init(id: "space1", isSpace: true)),
SpaceRoomProxyMock(.init(id: "space2", isSpace: true)), SpaceServiceRoomMock(.init(id: "space2", isSpace: true)),
SpaceRoomProxyMock(.init(id: "space3", isSpace: true)) SpaceServiceRoomMock(.init(id: "space3", isSpace: true))
]) ])
spaceServiceProxy = SpaceServiceProxyMock(.init()) spaceServiceProxy = SpaceServiceProxyMock(.init())
spaceServiceProxy.topLevelSpacesPublisher = topLevelSpacesSubject.asCurrentValuePublisher() spaceServiceProxy.topLevelSpacesPublisher = topLevelSpacesSubject.asCurrentValuePublisher()
spaceServiceProxy.spaceRoomListSpaceIDClosure = { [topLevelSpacesSubject] spaceID in spaceServiceProxy.spaceRoomListSpaceIDClosure = { [topLevelSpacesSubject] spaceID in
guard let spaceRoomProxy = topLevelSpacesSubject?.value.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } guard let spaceServiceRoom = topLevelSpacesSubject?.value.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) }
return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy))) return .success(SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom)))
} }
clientProxy.spaceService = spaceServiceProxy clientProxy.spaceService = spaceServiceProxy
@@ -16,7 +16,7 @@ import MatrixRustSDKMocks
@MainActor @MainActor
class SpaceScreenViewModelTests: XCTestCase { class SpaceScreenViewModelTests: XCTestCase {
var spaceRoomListProxy: SpaceRoomListProxyMock! var spaceRoomListProxy: SpaceRoomListProxyMock!
let mockSpaceRooms = [SpaceRoomProxyProtocol].mockSpaceList let mockSpaceRooms = [SpaceServiceRoomProtocol].mockSpaceList
var clientProxy: ClientProxyMock! var clientProxy: ClientProxyMock!
var paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never> = .init(.idle(endReached: true)) var paginationStateSubject: CurrentValueSubject<SpaceRoomListPaginationState, Never> = .init(.idle(endReached: true))
var rustLeaveHandle: LeaveSpaceHandleSDKMock! var rustLeaveHandle: LeaveSpaceHandleSDKMock!
@@ -118,7 +118,7 @@ class SpaceScreenViewModelTests: XCTestCase {
let action = try await deferred.fulfill() let action = try await deferred.fulfill()
switch action { switch action {
case .selectUnjoinedSpace(let spaceRoomProxy) where spaceRoomProxy.id == selectedSpace.id: case .selectUnjoinedSpace(let spaceServiceRoom) where spaceServiceRoom.id == selectedSpace.id:
break break
default: default:
XCTFail("The action should select the space.") XCTFail("The action should select the space.")
@@ -195,7 +195,7 @@ class SpaceScreenViewModelTests: XCTestCase {
leaveSpaceViewModel.context.send(viewAction: .deselectAll) leaveSpaceViewModel.context.send(viewAction: .deselectAll)
XCTAssertEqual(handle.selectedCount, 0, "Deselecting all should result in no selected rooms.") 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") 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. // Confirming the leave should leave the selected room and then the space.
@@ -205,21 +205,21 @@ class SpaceScreenViewModelTests: XCTestCase {
XCTAssertNil(context.leaveSpaceViewModel) XCTAssertNil(context.leaveSpaceViewModel)
XCTAssertTrue(rustLeaveHandle.leaveRoomIdsCalled) XCTAssertTrue(rustLeaveHandle.leaveRoomIdsCalled)
XCTAssertEqual(rustLeaveHandle.leaveRoomIdsReceivedRoomIds, 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.") "Confirming the leave should first leave the selected room and then the space.")
} }
// MARK: - Helpers // MARK: - Helpers
private func setupViewModel(paginationResponses: [[SpaceRoomProxyProtocol]] = []) { private func setupViewModel(paginationResponses: [[SpaceServiceRoomProtocol]] = []) {
spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: SpaceRoomProxyMock(.init(isSpace: true)), spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceServiceRoom: SpaceServiceRoomMock(.init(isSpace: true)),
paginationStateSubject: paginationStateSubject, paginationStateSubject: paginationStateSubject,
paginationResponses: paginationResponses)) paginationResponses: paginationResponses))
let spaceServiceProxy = SpaceServiceProxyMock(.init()) let spaceServiceProxy = SpaceServiceProxyMock(.init())
spaceServiceProxy.spaceRoomListSpaceIDClosure = { [mockSpaceRooms] spaceID in spaceServiceProxy.spaceRoomListSpaceIDClosure = { [mockSpaceRooms] spaceID in
guard let spaceRoomProxy = mockSpaceRooms.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) } guard let spaceServiceRoom = mockSpaceRooms.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) }
return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy))) return .success(SpaceRoomListProxyMock(.init(spaceServiceRoom: spaceServiceRoom)))
} }
let rustLeaveHandle = LeaveSpaceHandleSDKMock(.init()) let rustLeaveHandle = LeaveSpaceHandleSDKMock(.init())
spaceServiceProxy.leaveSpaceSpaceIDClosure = { spaceID in spaceServiceProxy.leaveSpaceSpaceIDClosure = { spaceID in