mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Add a SpaceScreen for listing rooms and subspaces within a space. (#4412)
This commit is contained in:
@@ -583,6 +583,10 @@ extension AccessibilityTests {
|
|||||||
try await performAccessibilityAudit(named: "SoftLogoutScreen_Previews")
|
try await performAccessibilityAudit(named: "SoftLogoutScreen_Previews")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSpaceHeaderView() async throws {
|
||||||
|
try await performAccessibilityAudit(named: "SpaceHeaderView_Previews")
|
||||||
|
}
|
||||||
|
|
||||||
func testSpaceListScreen() async throws {
|
func testSpaceListScreen() async throws {
|
||||||
try await performAccessibilityAudit(named: "SpaceListScreen_Previews")
|
try await performAccessibilityAudit(named: "SpaceListScreen_Previews")
|
||||||
}
|
}
|
||||||
@@ -591,6 +595,10 @@ extension AccessibilityTests {
|
|||||||
try await performAccessibilityAudit(named: "SpaceRoomCell_Previews")
|
try await performAccessibilityAudit(named: "SpaceRoomCell_Previews")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSpaceScreen() async throws {
|
||||||
|
try await performAccessibilityAudit(named: "SpaceScreen_Previews")
|
||||||
|
}
|
||||||
|
|
||||||
func testSplashScreen() async throws {
|
func testSplashScreen() async throws {
|
||||||
try await performAccessibilityAudit(named: "SplashScreen_Previews")
|
try await performAccessibilityAudit(named: "SplashScreen_Previews")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,6 +205,7 @@
|
|||||||
24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; };
|
24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; };
|
||||||
24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; };
|
24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; };
|
||||||
24C32D7EF94ECF9081638DF6 /* RemotePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A05E85E4872C3221C5C287 /* RemotePreference.swift */; };
|
24C32D7EF94ECF9081638DF6 /* RemotePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A05E85E4872C3221C5C287 /* RemotePreference.swift */; };
|
||||||
|
250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11397904D19CFF0E3689F0E /* SpaceScreenModels.swift */; };
|
||||||
25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; };
|
25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; };
|
||||||
256D76972BA3254F7CB7F88B /* LocationAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */; };
|
256D76972BA3254F7CB7F88B /* LocationAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */; };
|
||||||
25C4C1100B6EA79F5CC7CBB5 /* AppLockSetupPINScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */; };
|
25C4C1100B6EA79F5CC7CBB5 /* AppLockSetupPINScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */; };
|
||||||
@@ -482,6 +483,7 @@
|
|||||||
5992EF10AA157EBD97D88910 /* AudioRecorderState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6569593FA36B22259E806A67 /* AudioRecorderState.swift */; };
|
5992EF10AA157EBD97D88910 /* AudioRecorderState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6569593FA36B22259E806A67 /* AudioRecorderState.swift */; };
|
||||||
59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; };
|
59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; };
|
||||||
59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; };
|
59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; };
|
||||||
|
5A58C7C1837D3E5F2C3E8C8C /* SpaceScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8349149254469E24483FB0 /* SpaceScreenViewModel.swift */; };
|
||||||
5AA81A4E2D40A32A9E7F71F2 /* ShareExtensionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3ADF21BE301D0DA48F2A7E /* ShareExtensionView.swift */; };
|
5AA81A4E2D40A32A9E7F71F2 /* ShareExtensionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3ADF21BE301D0DA48F2A7E /* ShareExtensionView.swift */; };
|
||||||
5AC5CD6D893073EE4D9A277E /* ShareExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D27299A36536DBF91AE8FA6 /* ShareExtensionViewController.swift */; };
|
5AC5CD6D893073EE4D9A277E /* ShareExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D27299A36536DBF91AE8FA6 /* ShareExtensionViewController.swift */; };
|
||||||
5AE6404C4FD4848ACCFF9EDC /* SecureBackupLogoutConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */; };
|
5AE6404C4FD4848ACCFF9EDC /* SecureBackupLogoutConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */; };
|
||||||
@@ -526,6 +528,7 @@
|
|||||||
62C5876C4254C58C2086F0DE /* HomeScreenContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */; };
|
62C5876C4254C58C2086F0DE /* HomeScreenContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */; };
|
||||||
63780F9DA06573E38A471ECA /* GenericCallLinkWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C202C1C7E330F124981A31 /* GenericCallLinkWidgetDriver.swift */; };
|
63780F9DA06573E38A471ECA /* GenericCallLinkWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C202C1C7E330F124981A31 /* GenericCallLinkWidgetDriver.swift */; };
|
||||||
6386EA3C898AD1A4BC1DC8A5 /* TimelineMediaPreviewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */; };
|
6386EA3C898AD1A4BC1DC8A5 /* TimelineMediaPreviewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */; };
|
||||||
|
639A0A27383EC655B0E81E95 /* SpaceScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 459A3921046977CBF4F3C359 /* SpaceScreenViewModelProtocol.swift */; };
|
||||||
63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */; };
|
63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */; };
|
||||||
63DCEBC1DD555E0D645B9E98 /* MapTilerURLBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1033290D99D5BBA1AF3560A /* MapTilerURLBuilderProtocol.swift */; };
|
63DCEBC1DD555E0D645B9E98 /* MapTilerURLBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1033290D99D5BBA1AF3560A /* MapTilerURLBuilderProtocol.swift */; };
|
||||||
63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; };
|
63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; };
|
||||||
@@ -580,6 +583,7 @@
|
|||||||
6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; };
|
6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; };
|
||||||
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
|
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
|
||||||
6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; };
|
6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; };
|
||||||
|
6CAADDC6318E41C7D7AA9526 /* SpaceScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646B50583A2CE6DA67F7739A /* SpaceScreen.swift */; };
|
||||||
6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; };
|
6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; };
|
||||||
6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */; };
|
6DC8E43BA04AC2AC4EB2EB97 /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */; };
|
||||||
6E03A710799E6C65C0AB36BC /* TargetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D829FD8958376614504B18 /* TargetConfiguration.swift */; };
|
6E03A710799E6C65C0AB36BC /* TargetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D829FD8958376614504B18 /* TargetConfiguration.swift */; };
|
||||||
@@ -608,6 +612,7 @@
|
|||||||
71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */; };
|
71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */; };
|
||||||
71C1347F23868324A4F43940 /* NavigationModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */; };
|
71C1347F23868324A4F43940 /* NavigationModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */; };
|
||||||
7254FB2EFDD43BC8BB7A1213 /* SecurityAndPrivacyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */; };
|
7254FB2EFDD43BC8BB7A1213 /* SecurityAndPrivacyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */; };
|
||||||
|
72D2298DE695A6797CDA1A2A /* SpaceScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B223FA339BF53085328DEE /* SpaceScreenViewModelTests.swift */; };
|
||||||
733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */; };
|
733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */; };
|
||||||
738288EAEE235CAC0893AB9E /* ThreadTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C9ACDD96F36510C1FC0836B /* ThreadTimelineScreenViewModel.swift */; };
|
738288EAEE235CAC0893AB9E /* ThreadTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C9ACDD96F36510C1FC0836B /* ThreadTimelineScreenViewModel.swift */; };
|
||||||
73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; };
|
73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; };
|
||||||
@@ -1231,6 +1236,7 @@
|
|||||||
E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */; };
|
E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */; };
|
||||||
E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; };
|
E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; };
|
||||||
E9985DCD1B0D026D7E8BF809 /* ServerSelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6640DB5B9171D163E6742639 /* ServerSelectionTests.swift */; };
|
E9985DCD1B0D026D7E8BF809 /* ServerSelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6640DB5B9171D163E6742639 /* ServerSelectionTests.swift */; };
|
||||||
|
E9B4742B3D6E103327466513 /* SpaceHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3AAC314A877DBDB6EBE1170 /* SpaceHeaderView.swift */; };
|
||||||
E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */; };
|
E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718D8767035D37E2DB5CC550 /* QRCodeLoginScreenViewModelProtocol.swift */; };
|
||||||
EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; };
|
EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; };
|
||||||
EA2FECCD9E00D9784AC6017D /* PhishingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB07F03461023BC39C730922 /* PhishingDetector.swift */; };
|
EA2FECCD9E00D9784AC6017D /* PhishingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB07F03461023BC39C730922 /* PhishingDetector.swift */; };
|
||||||
@@ -1262,6 +1268,7 @@
|
|||||||
EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */; };
|
EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */; };
|
||||||
EED33AFD9334EFD7398707A6 /* VisualListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD529C89924EE32CE307F36F /* VisualListItem.swift */; };
|
EED33AFD9334EFD7398707A6 /* VisualListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD529C89924EE32CE307F36F /* VisualListItem.swift */; };
|
||||||
EF0D0155DD104C7A41A2EB0E /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; };
|
EF0D0155DD104C7A41A2EB0E /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; };
|
||||||
|
EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094F6B21835890B470DF540C /* SpaceScreenCoordinator.swift */; };
|
||||||
EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; };
|
EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; };
|
||||||
EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; };
|
EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; };
|
||||||
EF79B9EFD094C17FBB4942C2 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6DE144D887A254F4CAF203 /* UserPreference.swift */; };
|
EF79B9EFD094C17FBB4942C2 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6DE144D887A254F4CAF203 /* UserPreference.swift */; };
|
||||||
@@ -1495,6 +1502,7 @@
|
|||||||
0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectoriesTests.swift; sourceTree = "<group>"; };
|
0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectoriesTests.swift; sourceTree = "<group>"; };
|
||||||
08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsFlowCoordinator.swift; sourceTree = "<group>"; };
|
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
094F6B21835890B470DF540C /* SpaceScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
||||||
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; };
|
0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; };
|
||||||
@@ -1569,6 +1577,7 @@
|
|||||||
181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePreferenceTests.swift; sourceTree = "<group>"; };
|
181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePreferenceTests.swift; sourceTree = "<group>"; };
|
||||||
18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; };
|
18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; };
|
||||||
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
18B223FA339BF53085328DEE /* SpaceScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
|
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
|
||||||
190EC7285D3CFEF0D3011BCF /* GeoURI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURI.swift; sourceTree = "<group>"; };
|
190EC7285D3CFEF0D3011BCF /* GeoURI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURI.swift; sourceTree = "<group>"; };
|
||||||
196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenTrackerViewModifier.swift; sourceTree = "<group>"; };
|
196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenTrackerViewModifier.swift; sourceTree = "<group>"; };
|
||||||
@@ -1814,6 +1823,7 @@
|
|||||||
4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
4525E8C0FBDD27D1ACE90952 /* SecureBackupKeyBackupScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
4549FCB53F43DB0B278374BC /* TemplateScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreen.swift; sourceTree = "<group>"; };
|
4549FCB53F43DB0B278374BC /* TemplateScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreen.swift; sourceTree = "<group>"; };
|
||||||
4552D3466B1453F287223ADA /* SwipeRightAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeRightAction.swift; sourceTree = "<group>"; };
|
4552D3466B1453F287223ADA /* SwipeRightAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeRightAction.swift; sourceTree = "<group>"; };
|
||||||
|
459A3921046977CBF4F3C359 /* SpaceScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
45A4B934BA41D6C255900265 /* preview_video.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_video.jpg; sourceTree = "<group>"; };
|
45A4B934BA41D6C255900265 /* preview_video.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_video.jpg; sourceTree = "<group>"; };
|
||||||
45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = "<group>"; };
|
45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -1953,6 +1963,7 @@
|
|||||||
638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = "<group>"; };
|
638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = "<group>"; };
|
||||||
63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenModels.swift; sourceTree = "<group>"; };
|
645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenModels.swift; sourceTree = "<group>"; };
|
||||||
|
646B50583A2CE6DA67F7739A /* SpaceScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreen.swift; sourceTree = "<group>"; };
|
||||||
648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridableAvatarImage.swift; sourceTree = "<group>"; };
|
648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridableAvatarImage.swift; sourceTree = "<group>"; };
|
||||||
6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenCoordinator.swift; sourceTree = "<group>"; };
|
6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerScreenCoordinator.swift; sourceTree = "<group>"; };
|
64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
@@ -2418,6 +2429,7 @@
|
|||||||
BEE365C5A4E90ACBE398EFFE /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/SAS.strings; sourceTree = "<group>"; };
|
BEE365C5A4E90ACBE398EFFE /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||||
BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAvatarImage.swift; sourceTree = "<group>"; };
|
BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAvatarImage.swift; sourceTree = "<group>"; };
|
||||||
BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderScreenCoordinator.swift; sourceTree = "<group>"; };
|
BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
|
BF8349149254469E24483FB0 /* SpaceScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
BFA9EA59D5C0DA1BFC7B3621 /* QRCodeLoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreen.swift; sourceTree = "<group>"; };
|
BFA9EA59D5C0DA1BFC7B3621 /* QRCodeLoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreen.swift; sourceTree = "<group>"; };
|
||||||
BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; };
|
BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = "<group>"; };
|
BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = "<group>"; };
|
||||||
@@ -2430,6 +2442,7 @@
|
|||||||
C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedMessageTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedMessageTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenEmptyStateView.swift; sourceTree = "<group>"; };
|
C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenEmptyStateView.swift; sourceTree = "<group>"; };
|
||||||
C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModelTests.swift; sourceTree = "<group>"; };
|
C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
|
C11397904D19CFF0E3689F0E /* SpaceScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceScreenModels.swift; sourceTree = "<group>"; };
|
||||||
C142248014E08E885E323E56 /* Avatars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatars.swift; sourceTree = "<group>"; };
|
C142248014E08E885E323E56 /* Avatars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatars.swift; sourceTree = "<group>"; };
|
||||||
C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDirection.swift; sourceTree = "<group>"; };
|
C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDirection.swift; sourceTree = "<group>"; };
|
||||||
C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationModeProxy.swift; sourceTree = "<group>"; };
|
C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationModeProxy.swift; sourceTree = "<group>"; };
|
||||||
@@ -2687,6 +2700,7 @@
|
|||||||
F36C0A6D59717193F49EA986 /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = "<group>"; };
|
F36C0A6D59717193F49EA986 /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = "<group>"; };
|
||||||
F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenCoordinator.swift; sourceTree = "<group>"; };
|
F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; };
|
F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; };
|
||||||
|
F3AAC314A877DBDB6EBE1170 /* SpaceHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceHeaderView.swift; sourceTree = "<group>"; };
|
||||||
F3C7252B3461D06175D975A4 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/SAS.strings; sourceTree = "<group>"; };
|
F3C7252B3461D06175D975A4 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||||
F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxy.swift; sourceTree = "<group>"; };
|
F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxy.swift; sourceTree = "<group>"; };
|
||||||
F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModel.swift; sourceTree = "<group>"; };
|
F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
@@ -4531,6 +4545,7 @@
|
|||||||
9FE8A35B4AD5256F4B562274 /* SettingsScreenViewModelTests.swift */,
|
9FE8A35B4AD5256F4B562274 /* SettingsScreenViewModelTests.swift */,
|
||||||
AC43313F21511C853D34544E /* SoftLogoutScreenViewModelTests.swift */,
|
AC43313F21511C853D34544E /* SoftLogoutScreenViewModelTests.swift */,
|
||||||
5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */,
|
5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */,
|
||||||
|
18B223FA339BF53085328DEE /* SpaceScreenViewModelTests.swift */,
|
||||||
6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */,
|
6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */,
|
||||||
C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */,
|
C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */,
|
||||||
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */,
|
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */,
|
||||||
@@ -5576,6 +5591,7 @@
|
|||||||
BDDD421CD80AD0BCBA035076 /* Common */ = {
|
BDDD421CD80AD0BCBA035076 /* Common */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
F3AAC314A877DBDB6EBE1170 /* SpaceHeaderView.swift */,
|
||||||
A0E7B059E84E7E374D3322A2 /* SpaceRoomCell.swift */,
|
A0E7B059E84E7E374D3322A2 /* SpaceRoomCell.swift */,
|
||||||
);
|
);
|
||||||
path = Common;
|
path = Common;
|
||||||
@@ -5696,6 +5712,11 @@
|
|||||||
C360FCF7418FE3593D5A0CBF /* SpaceScreen */ = {
|
C360FCF7418FE3593D5A0CBF /* SpaceScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
094F6B21835890B470DF540C /* SpaceScreenCoordinator.swift */,
|
||||||
|
C11397904D19CFF0E3689F0E /* SpaceScreenModels.swift */,
|
||||||
|
BF8349149254469E24483FB0 /* SpaceScreenViewModel.swift */,
|
||||||
|
459A3921046977CBF4F3C359 /* SpaceScreenViewModelProtocol.swift */,
|
||||||
|
FA1D480A302295CFC3582543 /* View */,
|
||||||
);
|
);
|
||||||
path = SpaceScreen;
|
path = SpaceScreen;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -6302,6 +6323,14 @@
|
|||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
FA1D480A302295CFC3582543 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
646B50583A2CE6DA67F7739A /* SpaceScreen.swift */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
FB039572AA54E0690B4051AD /* Common */ = {
|
FB039572AA54E0690B4051AD /* Common */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -7228,6 +7257,7 @@
|
|||||||
494970EA811FE4D93AC68482 /* SettingsScreenViewModelTests.swift in Sources */,
|
494970EA811FE4D93AC68482 /* SettingsScreenViewModelTests.swift in Sources */,
|
||||||
C797C0B4CF45C66CD1921252 /* SoftLogoutScreenViewModelTests.swift in Sources */,
|
C797C0B4CF45C66CD1921252 /* SoftLogoutScreenViewModelTests.swift in Sources */,
|
||||||
920DC020F18ABC88175114D3 /* SpaceListScreenViewModelTests.swift in Sources */,
|
920DC020F18ABC88175114D3 /* SpaceListScreenViewModelTests.swift in Sources */,
|
||||||
|
72D2298DE695A6797CDA1A2A /* SpaceScreenViewModelTests.swift in Sources */,
|
||||||
6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */,
|
6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */,
|
||||||
9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */,
|
9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */,
|
||||||
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */,
|
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */,
|
||||||
@@ -8071,6 +8101,7 @@
|
|||||||
F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */,
|
F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */,
|
||||||
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */,
|
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */,
|
||||||
8D9A97E32C6C03B884CBD85A /* SpaceExplorerFlowCoordinator.swift in Sources */,
|
8D9A97E32C6C03B884CBD85A /* SpaceExplorerFlowCoordinator.swift in Sources */,
|
||||||
|
E9B4742B3D6E103327466513 /* SpaceHeaderView.swift in Sources */,
|
||||||
306ADA9D91EE5F0A30B5E500 /* SpaceListScreen.swift in Sources */,
|
306ADA9D91EE5F0A30B5E500 /* SpaceListScreen.swift in Sources */,
|
||||||
C586E1B286BCD8A774DA16B8 /* SpaceListScreenCoordinator.swift in Sources */,
|
C586E1B286BCD8A774DA16B8 /* SpaceListScreenCoordinator.swift in Sources */,
|
||||||
F38186A943D078D30BFB90DE /* SpaceListScreenModels.swift in Sources */,
|
F38186A943D078D30BFB90DE /* SpaceListScreenModels.swift in Sources */,
|
||||||
@@ -8081,6 +8112,11 @@
|
|||||||
2EAA1B35D9CA24F090F48792 /* SpaceRoomListProxyProtocol.swift in Sources */,
|
2EAA1B35D9CA24F090F48792 /* SpaceRoomListProxyProtocol.swift in Sources */,
|
||||||
C73CF79A578133D3AB7FB83D /* SpaceRoomProxyMock.swift in Sources */,
|
C73CF79A578133D3AB7FB83D /* SpaceRoomProxyMock.swift in Sources */,
|
||||||
BE8075CA131C5EA3665C9E0D /* SpaceRoomProxyProtocol.swift in Sources */,
|
BE8075CA131C5EA3665C9E0D /* SpaceRoomProxyProtocol.swift in Sources */,
|
||||||
|
6CAADDC6318E41C7D7AA9526 /* SpaceScreen.swift in Sources */,
|
||||||
|
EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */,
|
||||||
|
250D2E8309C8CC48796D41D1 /* SpaceScreenModels.swift in Sources */,
|
||||||
|
5A58C7C1837D3E5F2C3E8C8C /* SpaceScreenViewModel.swift in Sources */,
|
||||||
|
639A0A27383EC655B0E81E95 /* SpaceScreenViewModelProtocol.swift in Sources */,
|
||||||
A2091F4B1332D9BF273B09D5 /* SpaceServiceProxyMock.swift in Sources */,
|
A2091F4B1332D9BF273B09D5 /* SpaceServiceProxyMock.swift in Sources */,
|
||||||
DB5200B87C4CE9DF0024AC4E /* SpaceServiceProxyProtocol.swift in Sources */,
|
DB5200B87C4CE9DF0024AC4E /* SpaceServiceProxyProtocol.swift in Sources */,
|
||||||
DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */,
|
DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */,
|
||||||
|
|||||||
@@ -278,6 +278,7 @@
|
|||||||
"common_signing_out" = "Signing out";
|
"common_signing_out" = "Signing out";
|
||||||
"common_something_went_wrong" = "Something went wrong";
|
"common_something_went_wrong" = "Something went wrong";
|
||||||
"common_something_went_wrong_message" = "We encountered an issue. Please try again.";
|
"common_something_went_wrong_message" = "We encountered an issue. Please try again.";
|
||||||
|
"common_space" = "Space";
|
||||||
"common_starting_chat" = "Starting chat…";
|
"common_starting_chat" = "Starting chat…";
|
||||||
"common_sticker" = "Sticker";
|
"common_sticker" = "Sticker";
|
||||||
"common_success" = "Success";
|
"common_success" = "Success";
|
||||||
@@ -1075,6 +1076,7 @@
|
|||||||
"screen_roomlist_filter_favourites_empty_state_title" = "You don’t have favourite chats yet";
|
"screen_roomlist_filter_favourites_empty_state_title" = "You don’t have favourite chats yet";
|
||||||
"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites.";
|
"screen_roomlist_filter_invites_empty_state_title" = "You don't have any pending invites.";
|
||||||
"screen_roomlist_filter_low_priority" = "Low Priority";
|
"screen_roomlist_filter_low_priority" = "Low Priority";
|
||||||
|
"screen_roomlist_filter_low_priority_empty_state_title" = "You don’t have any low priority chats yet";
|
||||||
"screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats";
|
"screen_roomlist_filter_mixed_empty_state_subtitle" = "You can deselect filters in order to see your other chats";
|
||||||
"screen_roomlist_filter_mixed_empty_state_title" = "You don’t have chats for this selection";
|
"screen_roomlist_filter_mixed_empty_state_title" = "You don’t have chats for this selection";
|
||||||
"screen_roomlist_filter_people_empty_state_title" = "You don’t have any DMs yet";
|
"screen_roomlist_filter_people_empty_state_title" = "You don’t have any DMs yet";
|
||||||
|
|||||||
@@ -624,6 +624,8 @@ internal enum L10n {
|
|||||||
internal static var commonSomethingWentWrong: String { return L10n.tr("Localizable", "common_something_went_wrong") }
|
internal static var commonSomethingWentWrong: String { return L10n.tr("Localizable", "common_something_went_wrong") }
|
||||||
/// We encountered an issue. Please try again.
|
/// We encountered an issue. Please try again.
|
||||||
internal static var commonSomethingWentWrongMessage: String { return L10n.tr("Localizable", "common_something_went_wrong_message") }
|
internal static var commonSomethingWentWrongMessage: String { return L10n.tr("Localizable", "common_something_went_wrong_message") }
|
||||||
|
/// Space
|
||||||
|
internal static var commonSpace: String { return L10n.tr("Localizable", "common_space") }
|
||||||
/// Plural format key: "%#@COUNT@"
|
/// Plural format key: "%#@COUNT@"
|
||||||
internal static func commonSpaces(_ p1: Int) -> String {
|
internal static func commonSpaces(_ p1: Int) -> String {
|
||||||
return L10n.tr("Localizable", "common_spaces", p1)
|
return L10n.tr("Localizable", "common_spaces", p1)
|
||||||
@@ -2581,6 +2583,8 @@ internal enum L10n {
|
|||||||
internal static var screenRoomlistFilterInvitesEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_invites_empty_state_title") }
|
internal static var screenRoomlistFilterInvitesEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_invites_empty_state_title") }
|
||||||
/// Low Priority
|
/// Low Priority
|
||||||
internal static var screenRoomlistFilterLowPriority: String { return L10n.tr("Localizable", "screen_roomlist_filter_low_priority") }
|
internal static var screenRoomlistFilterLowPriority: String { return L10n.tr("Localizable", "screen_roomlist_filter_low_priority") }
|
||||||
|
/// You don’t have any low priority chats yet
|
||||||
|
internal static var screenRoomlistFilterLowPriorityEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_low_priority_empty_state_title") }
|
||||||
/// You can deselect filters in order to see your other chats
|
/// You can deselect filters in order to see your other chats
|
||||||
internal static var screenRoomlistFilterMixedEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_mixed_empty_state_subtitle") }
|
internal static var screenRoomlistFilterMixedEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_mixed_empty_state_subtitle") }
|
||||||
/// You don’t have chats for this selection
|
/// You don’t have chats for this selection
|
||||||
|
|||||||
@@ -5,19 +5,43 @@
|
|||||||
// Please see LICENSE files in the repository root for full details.
|
// Please see LICENSE files in the repository root for full details.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
|
|
||||||
extension SpaceRoomListProxyMock {
|
extension SpaceRoomListProxyMock {
|
||||||
struct Configuration {
|
class Configuration {
|
||||||
var spaceRoomProxy: SpaceRoomProxyProtocol
|
var spaceRoomProxy: SpaceRoomProxyProtocol
|
||||||
var spaceRooms: [SpaceRoomProxyProtocol] = []
|
var initialSpaceRooms: [SpaceRoomProxyProtocol]
|
||||||
|
var paginationStateSubject: CurrentValueSubject<SpaceRoomListProxyPaginationState, Never>
|
||||||
|
var paginationResponses: [[SpaceRoomProxyProtocol]]
|
||||||
|
|
||||||
|
init(spaceRoomProxy: SpaceRoomProxyProtocol,
|
||||||
|
initialSpaceRooms: [SpaceRoomProxyProtocol] = [],
|
||||||
|
paginationStateSubject: CurrentValueSubject<SpaceRoomListProxyPaginationState, Never> = .init(.idle(endReached: true)),
|
||||||
|
paginationResponses: [[SpaceRoomProxyProtocol]] = []) {
|
||||||
|
self.spaceRoomProxy = spaceRoomProxy
|
||||||
|
self.initialSpaceRooms = initialSpaceRooms
|
||||||
|
self.paginationStateSubject = paginationStateSubject
|
||||||
|
self.paginationResponses = paginationResponses
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convenience init(_ configuration: Configuration) {
|
convenience init(_ configuration: Configuration) {
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
|
let spaceRoomsSubject: CurrentValueSubject<[SpaceRoomProxyProtocol], Never> = .init(configuration.initialSpaceRooms)
|
||||||
|
|
||||||
spaceRoom = configuration.spaceRoomProxy
|
spaceRoom = configuration.spaceRoomProxy
|
||||||
spaceRoomsPublisher = .init(configuration.spaceRooms)
|
spaceRoomsPublisher = spaceRoomsSubject.asCurrentValuePublisher()
|
||||||
|
paginationStatePublisher = configuration.paginationStateSubject.asCurrentValuePublisher()
|
||||||
|
|
||||||
|
paginateClosure = {
|
||||||
|
configuration.paginationStateSubject.send(.loading)
|
||||||
|
try? await Task.sleep(for: .milliseconds(100))
|
||||||
|
let newRooms = configuration.paginationResponses.removeFirst()
|
||||||
|
spaceRoomsSubject.send(spaceRoomsSubject.value + newRooms)
|
||||||
|
configuration.paginationStateSubject.send(.idle(endReached: configuration.paginationResponses.isEmpty))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,3 +46,79 @@ extension SpaceRoomProxyMock {
|
|||||||
state = configuration.state
|
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 mockSpaceList: [SpaceRoomProxyProtocol] {
|
||||||
|
makeSpaceRooms(isSpace: true) + makeSpaceRooms(isSpace: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.",
|
||||||
|
state: .joined))
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ extension UserProfileProxy {
|
|||||||
.init(userID: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil)
|
.init(userID: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var mockDan: UserProfileProxy {
|
||||||
|
.init(userID: "@dan:matrix.org", displayName: "Dan", avatarURL: .mockMXCUserAvatar)
|
||||||
|
}
|
||||||
|
|
||||||
static var mockVerbose: UserProfileProxy {
|
static var mockVerbose: UserProfileProxy {
|
||||||
.init(userID: "@charlie:matrix.org", displayName: "Charlie is the best display name", avatarURL: nil)
|
.init(userID: "@charlie:matrix.org", displayName: "Charlie is the best display name", avatarURL: nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ enum UserAvatarSizeOnScreen {
|
|||||||
case readReceipt
|
case readReceipt
|
||||||
case readReceiptSheet
|
case readReceiptSheet
|
||||||
case editUserDetails
|
case editUserDetails
|
||||||
|
case spaceHeader
|
||||||
case completionSuggestions
|
case completionSuggestions
|
||||||
case blockedUsers
|
case blockedUsers
|
||||||
case knockingUsersBannerStack
|
case knockingUsersBannerStack
|
||||||
@@ -91,6 +92,8 @@ enum UserAvatarSizeOnScreen {
|
|||||||
return 16
|
return 16
|
||||||
case .readReceiptSheet:
|
case .readReceiptSheet:
|
||||||
return 32
|
return 32
|
||||||
|
case .spaceHeader:
|
||||||
|
return 20
|
||||||
case .completionSuggestions:
|
case .completionSuggestions:
|
||||||
return 32
|
return 32
|
||||||
case .blockedUsers:
|
case .blockedUsers:
|
||||||
|
|||||||
@@ -153,8 +153,10 @@ enum TestablePreviewsDictionary {
|
|||||||
"SettingsScreen_Previews" : SettingsScreen_Previews.self,
|
"SettingsScreen_Previews" : SettingsScreen_Previews.self,
|
||||||
"ShimmerOverlay_Previews" : ShimmerOverlay_Previews.self,
|
"ShimmerOverlay_Previews" : ShimmerOverlay_Previews.self,
|
||||||
"SoftLogoutScreen_Previews" : SoftLogoutScreen_Previews.self,
|
"SoftLogoutScreen_Previews" : SoftLogoutScreen_Previews.self,
|
||||||
|
"SpaceHeaderView_Previews" : SpaceHeaderView_Previews.self,
|
||||||
"SpaceListScreen_Previews" : SpaceListScreen_Previews.self,
|
"SpaceListScreen_Previews" : SpaceListScreen_Previews.self,
|
||||||
"SpaceRoomCell_Previews" : SpaceRoomCell_Previews.self,
|
"SpaceRoomCell_Previews" : SpaceRoomCell_Previews.self,
|
||||||
|
"SpaceScreen_Previews" : SpaceScreen_Previews.self,
|
||||||
"SplashScreen_Previews" : SplashScreen_Previews.self,
|
"SplashScreen_Previews" : SplashScreen_Previews.self,
|
||||||
"StackedAvatarsView_Previews" : StackedAvatarsView_Previews.self,
|
"StackedAvatarsView_Previews" : StackedAvatarsView_Previews.self,
|
||||||
"StartChatScreen_Previews" : StartChatScreen_Previews.self,
|
"StartChatScreen_Previews" : StartChatScreen_Previews.self,
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
//
|
||||||
|
// 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 Compound
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SpaceHeaderView: View {
|
||||||
|
let spaceRoomProxy: SpaceRoomProxyProtocol
|
||||||
|
let mediaProvider: MediaProviderProtocol?
|
||||||
|
|
||||||
|
var title: String { spaceRoomProxy.name ?? "" }
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 16) {
|
||||||
|
RoomAvatarImage(avatar: spaceRoomProxy.avatar,
|
||||||
|
avatarSize: .room(on: .spaceHeader),
|
||||||
|
mediaProvider: mediaProvider)
|
||||||
|
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
Text(title)
|
||||||
|
.font(.compound.headingLGBold)
|
||||||
|
.foregroundStyle(.compound.textPrimary)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
|
spaceDetails
|
||||||
|
|
||||||
|
SpaceHeaderMembersView(heroes: spaceRoomProxy.heroes,
|
||||||
|
joinedCount: spaceRoomProxy.joinedMembersCount,
|
||||||
|
mediaProvider: mediaProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let topic = spaceRoomProxy.topic {
|
||||||
|
Text(topic)
|
||||||
|
.font(.compound.bodyMD)
|
||||||
|
.foregroundStyle(.compound.textPrimary)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.lineLimit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.horizontal, 16)
|
||||||
|
.padding(.top, 32)
|
||||||
|
.padding(.bottom, 24)
|
||||||
|
.overlay(alignment: .bottom) {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color.compound.borderDisabled)
|
||||||
|
.frame(height: 1 / UIScreen.main.scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var spaceDetails: some View {
|
||||||
|
Label {
|
||||||
|
Text(L10n.screenSpaceListDetails(spaceDetailsVisibilityTitle, L10n.commonRooms(spaceRoomProxy.childrenCount)))
|
||||||
|
.font(.compound.bodyLG)
|
||||||
|
.foregroundStyle(.compound.textSecondary)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
} icon: {
|
||||||
|
CompoundIcon(spaceDetailsVisibilityIcon, size: .small, relativeTo: .compound.bodyLG)
|
||||||
|
.foregroundStyle(.compound.iconTertiary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var spaceDetailsVisibilityTitle: String {
|
||||||
|
switch spaceRoomProxy.joinRule {
|
||||||
|
case .public:
|
||||||
|
L10n.commonPublicSpace
|
||||||
|
case .restricted(let rules), .knockRestricted(let rules):
|
||||||
|
// FIXME: Get this from the rule (falling back to a passed in parent??)
|
||||||
|
"<Parent name> space"
|
||||||
|
case .invite, .knock, .private, .custom, .none:
|
||||||
|
L10n.commonPrivateSpace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var spaceDetailsVisibilityIcon: KeyPath<CompoundIcons, Image> {
|
||||||
|
switch spaceRoomProxy.joinRule {
|
||||||
|
case .public:
|
||||||
|
\.public
|
||||||
|
case .restricted, .knockRestricted:
|
||||||
|
\.space
|
||||||
|
case .invite, .knock, .private, .custom, .none:
|
||||||
|
\.lock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import MatrixRustSDK
|
||||||
|
|
||||||
|
struct SpaceHeaderMembersView: View {
|
||||||
|
let heroes: [UserProfileProxy]
|
||||||
|
let joinedCount: Int
|
||||||
|
|
||||||
|
let mediaProvider: MediaProviderProtocol?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if heroes.isEmpty {
|
||||||
|
Label(title: title) {
|
||||||
|
CompoundIcon(\.userProfile, size: .small, relativeTo: .compound.bodyMD)
|
||||||
|
.foregroundStyle(.compound.textSecondary)
|
||||||
|
}
|
||||||
|
.font(.compound.bodyMD)
|
||||||
|
.foregroundStyle(.compound.textSecondary)
|
||||||
|
.labelStyle(.custom(spacing: 4))
|
||||||
|
.padding(.trailing, 8)
|
||||||
|
.background(.compound.bgSubtleSecondary, in: Capsule())
|
||||||
|
} else {
|
||||||
|
Label(title: title) {
|
||||||
|
heroesFacePile
|
||||||
|
}
|
||||||
|
.font(.compound.bodyMD)
|
||||||
|
.foregroundStyle(.compound.textSecondary)
|
||||||
|
.labelStyle(.custom(spacing: 6))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func title() -> Text {
|
||||||
|
Text("\(joinedCount)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var heroesFacePile: some View {
|
||||||
|
HStack(spacing: -8) {
|
||||||
|
ForEach(heroes.prefix(3).reversed()) { hero in
|
||||||
|
LoadableAvatarImage(url: hero.avatarURL,
|
||||||
|
name: hero.displayName,
|
||||||
|
contentID: hero.userID,
|
||||||
|
avatarSize: .user(on: .spaceHeader),
|
||||||
|
mediaProvider: mediaProvider)
|
||||||
|
.mask {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.white)
|
||||||
|
.overlay {
|
||||||
|
if hero != heroes.first {
|
||||||
|
Circle()
|
||||||
|
.inset(by: -2)
|
||||||
|
.fill(Color.black)
|
||||||
|
.offset(x: 12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.compositingGroup()
|
||||||
|
.luminanceToAlpha()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpaceHeaderView_Previews: PreviewProvider, TestablePreview {
|
||||||
|
static let mediaProvider = MediaProviderMock(configuration: .init())
|
||||||
|
|
||||||
|
static let spaces = makeSpaceRooms()
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
ForEach(spaces, id: \.id) { space in
|
||||||
|
SpaceHeaderView(spaceRoomProxy: space, mediaProvider: mediaProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func makeSpaceRooms() -> [SpaceRoomProxyMock] {
|
||||||
|
[
|
||||||
|
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.",
|
||||||
|
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: " "),
|
||||||
|
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -136,8 +136,7 @@ struct SpaceRoomCellButtonStyle: ButtonStyle {
|
|||||||
struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview {
|
struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview {
|
||||||
static let mediaProvider = MediaProviderMock(configuration: .init())
|
static let mediaProvider = MediaProviderMock(configuration: .init())
|
||||||
|
|
||||||
static let spaces = makeSpaceRooms(isSpace: true)
|
static let spaces = [SpaceRoomProxyProtocol].mockSpaceList
|
||||||
static let rooms = makeSpaceRooms(isSpace: false)
|
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
@@ -146,34 +145,6 @@ struct SpaceRoomCell_Previews: PreviewProvider, TestablePreview {
|
|||||||
isSelected: false,
|
isSelected: false,
|
||||||
mediaProvider: mediaProvider) { _ in }
|
mediaProvider: mediaProvider) { _ in }
|
||||||
}
|
}
|
||||||
ForEach(rooms, id: \.id) { room in
|
|
||||||
SpaceRoomCell(spaceRoom: room,
|
|
||||||
isSelected: false,
|
|
||||||
mediaProvider: mediaProvider) { _ in }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static func makeSpaceRooms(isSpace: Bool) -> [SpaceRoomProxyMock] {
|
|
||||||
let name = isSpace ? "Space" : "Room"
|
|
||||||
|
|
||||||
return [
|
|
||||||
SpaceRoomProxyMock(.init(id: "!space1:matrix.org",
|
|
||||||
name: "Company \(name)",
|
|
||||||
isSpace: isSpace)),
|
|
||||||
SpaceRoomProxyMock(.init(id: "!space2:matrix.org",
|
|
||||||
name: "Public \(name)",
|
|
||||||
avatarURL: .mockMXCAvatar,
|
|
||||||
isSpace: isSpace,
|
|
||||||
joinedMembersCount: 78,
|
|
||||||
topic: "Discussion on specific topic goes here.",
|
|
||||||
joinRule: .public)),
|
|
||||||
SpaceRoomProxyMock(.init(id: "!space3:matrix.org",
|
|
||||||
name: "Joined \(name)",
|
|
||||||
isSpace: isSpace,
|
|
||||||
joinedMembersCount: 123,
|
|
||||||
topic: "Discussion on specific topic goes here.",
|
|
||||||
state: .joined))
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenVie
|
|||||||
mediaProvider: userSession.mediaProvider)
|
mediaProvider: userSession.mediaProvider)
|
||||||
|
|
||||||
spaceServiceProxy.joinedSpacesPublisher
|
spaceServiceProxy.joinedSpacesPublisher
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
.weakAssign(to: \.state.joinedSpaces, on: self)
|
.weakAssign(to: \.state.joinedSpaces, on: self)
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
|||||||
@@ -105,56 +105,9 @@ struct SpaceListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
static func makeViewModel(counterValue: Int = 0) -> SpaceListScreenViewModel {
|
static func makeViewModel(counterValue: Int = 0) -> SpaceListScreenViewModel {
|
||||||
let clientProxy = ClientProxyMock(.init())
|
let clientProxy = ClientProxyMock(.init())
|
||||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||||
let spaceService = SpaceServiceProxyMock(
|
let spaceService = SpaceServiceProxyMock(.init(joinedSpaces: .mockJoinedSpaces))
|
||||||
.init(
|
|
||||||
joinedSpaces: [
|
let viewModel = SpaceListScreenViewModel(userSession: userSession, spaceServiceProxy: spaceService)
|
||||||
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))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
let viewModel = SpaceListScreenViewModel(userSession: userSession,
|
|
||||||
spaceServiceProxy: spaceService)
|
|
||||||
|
|
||||||
return viewModel
|
return viewModel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
// periphery:ignore:all - this is just a space remove this comment once generating the final file
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SpaceScreenCoordinatorParameters {
|
||||||
|
let spaceRoomListProxy: SpaceRoomListProxyProtocol
|
||||||
|
let mediaProvider: MediaProviderProtocol
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SpaceScreenCoordinatorAction {
|
||||||
|
case selectSpace(SpaceRoomProxyProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
final class SpaceScreenCoordinator: CoordinatorProtocol {
|
||||||
|
private let parameters: SpaceScreenCoordinatorParameters
|
||||||
|
private let viewModel: SpaceScreenViewModelProtocol
|
||||||
|
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
private let actionsSubject: PassthroughSubject<SpaceScreenCoordinatorAction, Never> = .init()
|
||||||
|
var actionsPublisher: AnyPublisher<SpaceScreenCoordinatorAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: SpaceScreenCoordinatorParameters) {
|
||||||
|
self.parameters = parameters
|
||||||
|
|
||||||
|
viewModel = SpaceScreenViewModel(spaceRoomList: parameters.spaceRoomListProxy, mediaProvider: parameters.mediaProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
viewModel.actionsPublisher.sink { [weak self] action in
|
||||||
|
MXLog.info("Coordinator: received view model action: \(action)")
|
||||||
|
|
||||||
|
guard let self else { return }
|
||||||
|
switch action {
|
||||||
|
case .selectSpace(let spaceRoom):
|
||||||
|
actionsSubject.send(.selectSpace(spaceRoom))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPresentable() -> AnyView {
|
||||||
|
AnyView(SpaceScreen(context: viewModel.context))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
enum SpaceScreenViewModelAction {
|
||||||
|
case selectSpace(SpaceRoomProxyProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpaceScreenViewState: BindableState {
|
||||||
|
let space: SpaceRoomProxyProtocol
|
||||||
|
|
||||||
|
var isPaginating = false
|
||||||
|
var rooms: [SpaceRoomProxyProtocol]
|
||||||
|
|
||||||
|
var bindings = SpaceScreenViewStateBindings()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpaceScreenViewStateBindings { }
|
||||||
|
|
||||||
|
enum SpaceScreenViewAction {
|
||||||
|
case spaceAction(SpaceRoomCell.Action)
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// 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 Combine
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
typealias SpaceScreenViewModelType = StateStoreViewModelV2<SpaceScreenViewState, SpaceScreenViewAction>
|
||||||
|
|
||||||
|
class SpaceScreenViewModel: SpaceScreenViewModelType, SpaceScreenViewModelProtocol {
|
||||||
|
private let actionsSubject: PassthroughSubject<SpaceScreenViewModelAction, Never> = .init()
|
||||||
|
var actionsPublisher: AnyPublisher<SpaceScreenViewModelAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(spaceRoomList: SpaceRoomListProxyProtocol, mediaProvider: MediaProviderProtocol) {
|
||||||
|
super.init(initialViewState: SpaceScreenViewState(space: spaceRoomList.spaceRoom,
|
||||||
|
rooms: spaceRoomList.spaceRoomsPublisher.value),
|
||||||
|
mediaProvider: mediaProvider)
|
||||||
|
|
||||||
|
spaceRoomList.spaceRoomsPublisher
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.weakAssign(to: \.state.rooms, on: self)
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
spaceRoomList.paginationStatePublisher
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] paginationState in
|
||||||
|
switch paginationState {
|
||||||
|
case .idle(let endReached):
|
||||||
|
self?.state.isPaginating = false
|
||||||
|
guard !endReached else { return }
|
||||||
|
Task { await spaceRoomList.paginate() }
|
||||||
|
case .loading:
|
||||||
|
self?.state.isPaginating = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
override func process(viewAction: SpaceScreenViewAction) {
|
||||||
|
MXLog.info("View model: received view action: \(viewAction)")
|
||||||
|
|
||||||
|
switch viewAction {
|
||||||
|
case .spaceAction(.select(let spaceRoom)):
|
||||||
|
if spaceRoom.isSpace {
|
||||||
|
actionsSubject.send(.selectSpace(spaceRoom))
|
||||||
|
} else {
|
||||||
|
#warning("Implement joining")
|
||||||
|
}
|
||||||
|
case .spaceAction(.join(let spaceID)):
|
||||||
|
#warning("Implement joining.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// 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 Combine
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
protocol SpaceScreenViewModelProtocol {
|
||||||
|
var actionsPublisher: AnyPublisher<SpaceScreenViewModelAction, Never> { get }
|
||||||
|
var context: SpaceScreenViewModelType.Context { get }
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// 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 Compound
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SpaceScreen: View {
|
||||||
|
@Bindable var context: SpaceScreenViewModel.Context
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
LazyVStack(spacing: 0) {
|
||||||
|
SpaceHeaderView(spaceRoomProxy: context.viewState.space,
|
||||||
|
mediaProvider: context.mediaProvider)
|
||||||
|
rooms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle(context.viewState.space.name ?? L10n.commonSpace)
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
var rooms: some View {
|
||||||
|
ForEach(context.viewState.rooms, id: \.id) { spaceRoom in
|
||||||
|
SpaceRoomCell(spaceRoom: spaceRoom,
|
||||||
|
isSelected: false,
|
||||||
|
mediaProvider: context.mediaProvider) { action in
|
||||||
|
context.send(viewAction: .spaceAction(action))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.viewState.isPaginating {
|
||||||
|
ProgressView()
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Previews
|
||||||
|
|
||||||
|
struct SpaceScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
|
static let viewModel = makeViewModel()
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
NavigationStack {
|
||||||
|
SpaceScreen(context: viewModel.context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.",
|
||||||
|
joinRule: .knockRestricted(rules: [.roomMembership(roomId: "")])))
|
||||||
|
let spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy,
|
||||||
|
initialSpaceRooms: .mockSpaceList))
|
||||||
|
|
||||||
|
let viewModel = SpaceScreenViewModel(spaceRoomList: spaceRoomListProxy,
|
||||||
|
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||||
|
return viewModel
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import Combine
|
|||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
|
|
||||||
// Temporary until the SDK is updated.
|
// Temporary until the SDK is updated.
|
||||||
enum SpaceRoomListProxyPaginationState {
|
enum SpaceRoomListProxyPaginationState: Equatable {
|
||||||
case idle(endReached: Bool)
|
case idle(endReached: Bool)
|
||||||
case loading
|
case loading
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -875,6 +875,12 @@ extension PreviewTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSpaceHeaderView() async throws {
|
||||||
|
for (index, preview) in SpaceHeaderView_Previews._allPreviews.enumerated() {
|
||||||
|
try await assertSnapshots(matching: preview, step: index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testSpaceListScreen() async throws {
|
func testSpaceListScreen() async throws {
|
||||||
for (index, preview) in SpaceListScreen_Previews._allPreviews.enumerated() {
|
for (index, preview) in SpaceListScreen_Previews._allPreviews.enumerated() {
|
||||||
try await assertSnapshots(matching: preview, step: index)
|
try await assertSnapshots(matching: preview, step: index)
|
||||||
@@ -887,6 +893,12 @@ extension PreviewTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSpaceScreen() async throws {
|
||||||
|
for (index, preview) in SpaceScreen_Previews._allPreviews.enumerated() {
|
||||||
|
try await assertSnapshots(matching: preview, step: index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testSplashScreen() async throws {
|
func testSplashScreen() async throws {
|
||||||
for (index, preview) in SplashScreen_Previews._allPreviews.enumerated() {
|
for (index, preview) in SplashScreen_Previews._allPreviews.enumerated() {
|
||||||
try await assertSnapshots(matching: preview, step: index)
|
try await assertSnapshots(matching: preview, step: index)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d89f971df09420eeb3e2393d12851c50da0896366fd914df6e50f8525b1963bc
|
||||||
|
size 207443
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:80d43f3c8bd54048177b925efe184e6324da54a6c342ed2f5629983a15ec946a
|
||||||
|
size 223500
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:11b7484b43434f0d598cc596e7eaaa9d898d25b3aba4dfe9d05bdc78ea9b8187
|
||||||
|
size 138715
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e5ea7da5f53f16d9d7eba70450c61ef7ec6b93f70148d32b0152ffa6ec211c33
|
||||||
|
size 164457
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:04df1d04edeac89a7321c3e02ed38ee85bfa0946337896a334d89d8c561195ff
|
oid sha256:5e2b6b775f3a198e0a52991a296bc1ad5756af00b67c3e867eac90313e62513a
|
||||||
size 207862
|
size 207919
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9eda888ec16f20eb1f116ce198ef518cdeb2795c8c59b674c0d537cca2acdc97
|
oid sha256:f95f1258a7467c48a260c4d9968822f7e4a68f07e664c115f9d6a127c1cd2cf6
|
||||||
size 237007
|
size 237067
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:2cf45ff8958dfa9af8bd456e0d72c94c70d769461394ec028dcbe120ba714957
|
oid sha256:104cfb4b0707e035efd03a941da0da8a6c01d189e8d1b66ec1ed4ef1e245062c
|
||||||
size 149449
|
size 149502
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:bf1fd488f8022708dcedfd1f367b3cf688e9153e5505c1657810d6f4959b76a0
|
oid sha256:b4fb5143447b96770909c6a0daddb237e64a3df4e0a48b7aa0d3a60e18c7e586
|
||||||
size 167283
|
size 167301
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8a9a4c1899fffb9c101f87eeeb2413c962f72daddb2bdf10b23c1aa8267a6707
|
||||||
|
size 241775
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4debd3d362dfdcec1eebbade1159b3cbbafad46e2daacb1511ad2d08c847926e
|
||||||
|
size 279363
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e1cac5e788e68553c910fcf9d10213c025c593763e72e448db359b2a50f06bd0
|
||||||
|
size 186591
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:90a7af41076c73f8fc3671d6402bdc9e93e23ea592c7efa6647242c44541a900
|
||||||
|
size 206847
|
||||||
@@ -27,15 +27,19 @@ class SpaceListScreenViewModelTests: XCTestCase {
|
|||||||
XCTAssertEqual(context.viewState.joinedRoomsCount, 0)
|
XCTAssertEqual(context.viewState.joinedRoomsCount, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJoinedSpacesSubscription() {
|
func testJoinedSpacesSubscription() async throws {
|
||||||
setupViewModel()
|
setupViewModel()
|
||||||
|
|
||||||
|
var deferred = deferFulfillment(context.observe(\.viewState.joinedSpaces)) { $0.count == 0 }
|
||||||
joinedSpacesSubject.send([])
|
joinedSpacesSubject.send([])
|
||||||
|
try await deferred.fulfill()
|
||||||
XCTAssertEqual(context.viewState.joinedSpaces.count, 0)
|
XCTAssertEqual(context.viewState.joinedSpaces.count, 0)
|
||||||
|
|
||||||
|
deferred = deferFulfillment(context.observe(\.viewState.joinedSpaces)) { $0.count == 1 }
|
||||||
joinedSpacesSubject.send([
|
joinedSpacesSubject.send([
|
||||||
SpaceRoomProxyMock(.init(isSpace: true))
|
SpaceRoomProxyMock(.init(isSpace: true))
|
||||||
])
|
])
|
||||||
|
try await deferred.fulfill()
|
||||||
XCTAssertEqual(context.viewState.joinedSpaces.count, 1)
|
XCTAssertEqual(context.viewState.joinedSpaces.count, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
//
|
||||||
|
// 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 Combine
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import ElementX
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class SpaceScreenViewModelTests: XCTestCase {
|
||||||
|
var spaceRoomListProxy: SpaceRoomListProxyMock!
|
||||||
|
let mockSpaceRooms = [SpaceRoomProxyProtocol].mockSpaceList
|
||||||
|
var paginationStateSubject: CurrentValueSubject<SpaceRoomListProxyPaginationState, Never> = .init(.idle(endReached: true))
|
||||||
|
|
||||||
|
var viewModel: SpaceScreenViewModelProtocol!
|
||||||
|
|
||||||
|
var context: SpaceScreenViewModelType.Context {
|
||||||
|
viewModel.context
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInitialState() {
|
||||||
|
setupViewModel()
|
||||||
|
|
||||||
|
XCTAssertFalse(context.viewState.isPaginating)
|
||||||
|
XCTAssertTrue(context.viewState.rooms.isEmpty)
|
||||||
|
XCTAssertFalse(spaceRoomListProxy.paginateCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSinglePagination() async throws {
|
||||||
|
// Given a space screen view model for a space with a single paginations worth of children.
|
||||||
|
let response = mockSpaceRooms.prefix(3)
|
||||||
|
setupViewModel(paginationResponses: [Array(response)])
|
||||||
|
|
||||||
|
XCTAssertFalse(context.viewState.isPaginating)
|
||||||
|
XCTAssertTrue(context.viewState.rooms.isEmpty)
|
||||||
|
XCTAssertFalse(spaceRoomListProxy.paginateCalled)
|
||||||
|
XCTAssertFalse(response.isEmpty, "There should be some test rooms.")
|
||||||
|
|
||||||
|
// When the pagination is triggered.
|
||||||
|
var deferred = deferFulfillment(spaceRoomListProxy.paginationStatePublisher) { $0 == .loading }
|
||||||
|
paginationStateSubject.send(.idle(endReached: false)) // Invert the default to allow paginate to be called.
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
// Then the screen should show a paginating indicator.
|
||||||
|
XCTAssertTrue(context.viewState.isPaginating)
|
||||||
|
XCTAssertEqual(spaceRoomListProxy.paginateCallsCount, 1)
|
||||||
|
|
||||||
|
// When waiting for the pagination to finish.
|
||||||
|
deferred = deferFulfillment(spaceRoomListProxy.paginationStatePublisher) { $0 == .idle(endReached: true) }
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
// Then no more pagination requests should be made the the space rooms should be populated.
|
||||||
|
XCTAssertFalse(context.viewState.isPaginating)
|
||||||
|
XCTAssertEqual(spaceRoomListProxy.paginateCallsCount, 1)
|
||||||
|
XCTAssertEqual(context.viewState.rooms.map(\.id), response.map(\.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultiplePaginations() async throws {
|
||||||
|
// Given a space screen view model for a space with two distinct paginations worth of children.
|
||||||
|
let response1 = mockSpaceRooms.prefix(3)
|
||||||
|
let response2 = mockSpaceRooms.suffix(mockSpaceRooms.count - 3)
|
||||||
|
setupViewModel(paginationResponses: [Array(response1), Array(response2)])
|
||||||
|
|
||||||
|
XCTAssertFalse(context.viewState.isPaginating)
|
||||||
|
XCTAssertTrue(context.viewState.rooms.isEmpty)
|
||||||
|
XCTAssertFalse(spaceRoomListProxy.paginateCalled)
|
||||||
|
XCTAssertFalse(response1.isEmpty, "There should be some test rooms.")
|
||||||
|
XCTAssertFalse(response2.isEmpty, "There should be more test rooms.")
|
||||||
|
|
||||||
|
// When the pagination is triggered.
|
||||||
|
let deferredIsPaginating = deferFulfillment(context.observe(\.viewState.isPaginating), transitionValues: [true, false, true, false])
|
||||||
|
let deferredState = deferFulfillment(spaceRoomListProxy.paginationStatePublisher, keyPath: \.self, transitionValues: [.loading,
|
||||||
|
.idle(endReached: false),
|
||||||
|
.loading,
|
||||||
|
.idle(endReached: true)])
|
||||||
|
paginationStateSubject.send(.idle(endReached: false)) // Invert the default to allow paginate to be called.
|
||||||
|
|
||||||
|
// Then the screen should show 2 distinct paginations and finish up with all of the rooms visible.
|
||||||
|
try await deferredIsPaginating.fulfill()
|
||||||
|
try await deferredState.fulfill()
|
||||||
|
|
||||||
|
XCTAssertFalse(context.viewState.isPaginating)
|
||||||
|
XCTAssertEqual(spaceRoomListProxy.paginateCallsCount, 2)
|
||||||
|
XCTAssertEqual(context.viewState.rooms.map(\.id), mockSpaceRooms.map(\.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSelectingSpace() async throws {
|
||||||
|
setupViewModel()
|
||||||
|
|
||||||
|
let selectedSpace = mockSpaceRooms[0]
|
||||||
|
let deferred = deferFulfillment(viewModel.actionsPublisher) { _ in true }
|
||||||
|
viewModel.context.send(viewAction: .spaceAction(.select(selectedSpace)))
|
||||||
|
let action = try await deferred.fulfill()
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .selectSpace(let spaceRoomProxy) where spaceRoomProxy.id == selectedSpace.id:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
XCTFail("The action should select the space.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
private func setupViewModel(paginationResponses: [[SpaceRoomProxyProtocol]] = []) {
|
||||||
|
spaceRoomListProxy = SpaceRoomListProxyMock(.init(spaceRoomProxy: SpaceRoomProxyMock(.init(isSpace: true)),
|
||||||
|
paginationStateSubject: paginationStateSubject,
|
||||||
|
paginationResponses: paginationResponses))
|
||||||
|
|
||||||
|
viewModel = SpaceScreenViewModel(spaceRoomList: spaceRoomListProxy,
|
||||||
|
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user