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