Initial setup for the SpaceListScreen. (#4380)

This commit is contained in:
Doug
2025-08-05 11:06:26 +01:00
committed by GitHub
parent 69223b9601
commit fead5ff191
20 changed files with 356 additions and 6 deletions

View File

@@ -583,6 +583,10 @@ extension AccessibilityTests {
try await performAccessibilityAudit(named: "SoftLogoutScreen_Previews")
}
func testSpaceListScreen() async throws {
try await performAccessibilityAudit(named: "SpaceListScreen_Previews")
}
func testSplashScreen() async throws {
try await performAccessibilityAudit(named: "SplashScreen_Previews")
}

View File

@@ -144,6 +144,7 @@
182D532B736178A1DED9F76E /* ReportRoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FCAE847556719BBE7A0882 /* ReportRoomScreenModels.swift */; };
18386B777FDA74E4B3282D4F /* TimelineItemThreadSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98C6A082F2B2A15E1B9BE280 /* TimelineItemThreadSummary.swift */; };
18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
188B0E4EA6CE5711A0566087 /* SpaceListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752814FC7CE5A730B04F8142 /* SpaceListScreenViewModel.swift */; };
18978C9438206828C1D5AF2A /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */; };
18E3786918486D4C9726BC84 /* FormButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.swift */; };
18FDE4ED6D83B0771452B43D /* RoomSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F104596B0620CEFE5DFD31B1 /* RoomSelectionScreenCoordinator.swift */; };
@@ -637,6 +638,7 @@
784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; };
785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */; };
7856DE3EA4580AE0329986EB /* ComposerDraftServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E600B315B920B9687F8EE1B /* ComposerDraftServiceMock.swift */; };
789C3667354AE2DD9646ECB8 /* SpaceListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005CA6F5F5088A8868DC6CED /* SpaceListScreen.swift */; };
78A3D84BA47DAC69B4D0A34C /* CollapsibleRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBF273BC2BFB9F3EEFA988B /* CollapsibleRoomTimelineView.swift */; };
795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */; };
@@ -688,6 +690,7 @@
80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; };
80F1B442DB5E2C362ACDD8E2 /* ZoomTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018194CAFBE80720FECCEDEE /* ZoomTransition.swift */; };
80F6C8EFCA4564B67F0D34B0 /* DeactivateAccountScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77F75B3E9F99864048A422A /* DeactivateAccountScreenViewModelTests.swift */; };
8182E5914C729ABA646B1B5F /* SpaceListScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503AADD7C9021C4E0ED92323 /* SpaceListScreenCoordinator.swift */; };
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; };
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; };
828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */; };
@@ -779,6 +782,7 @@
91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; };
91D1A46A733EC24C081DD353 /* SessionVerificationRequestDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1265FAF2C0AF1C30605BE7 /* SessionVerificationRequestDetailsView.swift */; };
92012C96039BC8C2CAEBA9E2 /* AuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671C338B7259DC5774816885 /* AuthenticationServiceTests.swift */; };
920DC020F18ABC88175114D3 /* SpaceListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */; };
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
92720AB0DA9AB5EEF1DAF56B /* SecureBackupLogoutConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DC017C3CB6B0F7C63F460F2 /* SecureBackupLogoutConfirmationScreenViewModel.swift */; };
9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */; };
@@ -1283,6 +1287,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 */; };
F50C34684647D8357A460BC8 /* SpaceListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB311E22D08E85017E15FC0 /* SpaceListScreenModels.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 */; };
@@ -1307,6 +1312,7 @@
F86102DC2C68BBBB0521BAAE /* SoftLogoutScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */; };
F8B2F5CBCF2A0E0798E8D646 /* TimelineViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */; };
F8C87130FD999F7F1076208C /* RoomChangePermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AAEA70CFF3284920811941 /* RoomChangePermissionsScreen.swift */; };
F8D8E142445CB4628F7DC533 /* SpaceListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6949BC5A16D9BDD932FF93D /* SpaceListScreenViewModelProtocol.swift */; };
F8E725D42023ECA091349245 /* AudioRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57EAAF82432B0B53881CF826 /* AudioRoomTimelineItem.swift */; };
F8F47CE757EE656905F01F2C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90DFF217B3D9D0941283278C /* RoomRolesAndPermissionsScreenViewModelProtocol.swift */; };
F9788AE0B9EA19F1190ED14F /* StartChatScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B927A399A5418DA40A5CA15 /* StartChatScreenTests.swift */; };
@@ -1429,6 +1435,7 @@
/* Begin PBXFileReference section */
002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreen.swift; sourceTree = "<group>"; };
00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = "<group>"; };
005CA6F5F5088A8868DC6CED /* SpaceListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreen.swift; sourceTree = "<group>"; };
00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = "<group>"; };
00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelTests.swift; sourceTree = "<group>"; };
011AFA4990C585D157829679 /* DeclineAndBlockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineAndBlockScreenViewModel.swift; sourceTree = "<group>"; };
@@ -1502,6 +1509,7 @@
0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentionalMentions.swift; sourceTree = "<group>"; };
0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitedRoomProxy.swift; sourceTree = "<group>"; };
0EB311E22D08E85017E15FC0 /* SpaceListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenModels.swift; sourceTree = "<group>"; };
0EE9EAF0309A2A1D67D8FAF5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenModels.swift; sourceTree = "<group>"; };
@@ -1844,6 +1852,7 @@
4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomFlowCoordinatorTests.swift; sourceTree = "<group>"; };
4FDD775CFD72DD2D3C8A8390 /* NotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxyProtocol.swift; sourceTree = "<group>"; };
502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenModels.swift; sourceTree = "<group>"; };
503AADD7C9021C4E0ED92323 /* SpaceListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenCoordinator.swift; sourceTree = "<group>"; };
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
505ADA084C0B38A0C4AD2574 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -1869,6 +1878,7 @@
54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenModels.swift; sourceTree = "<group>"; };
54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReactionsView.swift; sourceTree = "<group>"; };
54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
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>"; };
5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSoftLogoutScreenState.swift; sourceTree = "<group>"; };
@@ -2012,6 +2022,7 @@
74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenCoordinator.swift; sourceTree = "<group>"; };
74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
7509AB72755DCC4B4E721B36 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/SAS.strings; sourceTree = "<group>"; };
752814FC7CE5A730B04F8142 /* SpaceListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenViewModel.swift; sourceTree = "<group>"; };
752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signposter.swift; sourceTree = "<group>"; };
753B4C6C0EDDCBF0708DC384 /* TimelineItemSendInfoLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSendInfoLabel.swift; sourceTree = "<group>"; };
75821CD31A4BD02B99C327A4 /* DataProtectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProtectionManager.swift; sourceTree = "<group>"; };
@@ -2348,6 +2359,7 @@
B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = "<group>"; };
B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = "<group>"; };
B68B31232312AFC844440BFE /* DeclineAndBlockScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineAndBlockScreenModels.swift; sourceTree = "<group>"; };
B6949BC5A16D9BDD932FF93D /* SpaceListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceListScreenViewModelProtocol.swift; sourceTree = "<group>"; };
B69AEA8755382DB34892FB7B /* ThreadTimelineScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadTimelineScreenModels.swift; sourceTree = "<group>"; };
B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = "<group>"; };
B6C585CE1F721A2770C70D47 /* TimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerProtocol.swift; sourceTree = "<group>"; };
@@ -3024,6 +3036,18 @@
path = CallScreen;
sourceTree = "<group>";
};
12E4648360EEC92520C6BC7E /* SpaceListScreen */ = {
isa = PBXGroup;
children = (
503AADD7C9021C4E0ED92323 /* SpaceListScreenCoordinator.swift */,
0EB311E22D08E85017E15FC0 /* SpaceListScreenModels.swift */,
752814FC7CE5A730B04F8142 /* SpaceListScreenViewModel.swift */,
B6949BC5A16D9BDD932FF93D /* SpaceListScreenViewModelProtocol.swift */,
CF870CEE51C0AEFABBB525FE /* View */,
);
path = SpaceListScreen;
sourceTree = "<group>";
};
13263FFEA7749D822B51AA90 /* AppLock */ = {
isa = PBXGroup;
children = (
@@ -4489,6 +4513,7 @@
DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */,
9FE8A35B4AD5256F4B562274 /* SettingsScreenViewModelTests.swift */,
AC43313F21511C853D34544E /* SoftLogoutScreenViewModelTests.swift */,
5557DDA438841AF5DC003D0B /* SpaceListScreenViewModelTests.swift */,
6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */,
C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */,
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */,
@@ -5740,6 +5765,14 @@
path = Layout;
sourceTree = "<group>";
};
CF870CEE51C0AEFABBB525FE /* View */ = {
isa = PBXGroup;
children = (
005CA6F5F5088A8868DC6CED /* SpaceListScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
D0111119CDF3E28E6D7768E8 /* ShareExtension */ = {
isa = PBXGroup;
children = (
@@ -5997,6 +6030,7 @@
2565414373E6F68005966B8E /* SecureBackup */,
C59BA103987B953BA374509F /* SecurityAndPrivacyScreen */,
70B74A432C241E56A7ACE610 /* Settings */,
12E4648360EEC92520C6BC7E /* SpaceListScreen */,
EC4545C7E37E8294D3FE6800 /* StartChatScreen */,
9688AEF931DE2C71683ACBC7 /* ThreadTimelineScreen */,
15D44FCA9475E660B7F56DB9 /* Timeline */,
@@ -7120,6 +7154,7 @@
755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */,
494970EA811FE4D93AC68482 /* SettingsScreenViewModelTests.swift in Sources */,
C797C0B4CF45C66CD1921252 /* SoftLogoutScreenViewModelTests.swift in Sources */,
920DC020F18ABC88175114D3 /* SpaceListScreenViewModelTests.swift in Sources */,
6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */,
9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */,
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */,
@@ -7960,6 +7995,11 @@
F86102DC2C68BBBB0521BAAE /* SoftLogoutScreenModels.swift in Sources */,
F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */,
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */,
789C3667354AE2DD9646ECB8 /* SpaceListScreen.swift in Sources */,
8182E5914C729ABA646B1B5F /* SpaceListScreenCoordinator.swift in Sources */,
F50C34684647D8357A460BC8 /* SpaceListScreenModels.swift in Sources */,
188B0E4EA6CE5711A0566087 /* SpaceListScreenViewModel.swift in Sources */,
F8D8E142445CB4628F7DC533 /* SpaceListScreenViewModelProtocol.swift in Sources */,
DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */,
E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */,
3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */,

View File

@@ -74,6 +74,11 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
isNewLogin: isNewLogin)
chatsTabDetails = .init(tag: HomeTab.chats, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid)
chatsTabDetails.barVisibility = .hidden
// This is just temporary, it needs a flow coordinator to properly handle (amongst other things) navigation/split views.
let spaceListScreenCoordinator = SpaceListScreenCoordinator(parameters: .init(userSession: userSession))
let spacesNavigationCoordinator = NavigationStackCoordinator()
spacesNavigationCoordinator.setRootCoordinator(spaceListScreenCoordinator)
spacesTabDetails = .init(tag: HomeTab.spaces, title: L10n.screenHomeTabSpaces, icon: \.space, selectedIcon: \.spaceSolid)
onboardingStackCoordinator = NavigationStackCoordinator()
@@ -89,7 +94,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
navigationTabCoordinator.setTabs([
.init(coordinator: chatsSplitCoordinator, details: chatsTabDetails),
.init(coordinator: BlankFormCoordinator(), details: spacesTabDetails)
.init(coordinator: spacesNavigationCoordinator, details: spacesTabDetails)
])
setupObservers()

View File

@@ -153,6 +153,7 @@ enum TestablePreviewsDictionary {
"SettingsScreen_Previews" : SettingsScreen_Previews.self,
"ShimmerOverlay_Previews" : ShimmerOverlay_Previews.self,
"SoftLogoutScreen_Previews" : SoftLogoutScreen_Previews.self,
"SpaceListScreen_Previews" : SpaceListScreen_Previews.self,
"SplashScreen_Previews" : SplashScreen_Previews.self,
"StackedAvatarsView_Previews" : StackedAvatarsView_Previews.self,
"StartChatScreen_Previews" : StartChatScreen_Previews.self,

View File

@@ -0,0 +1,54 @@
//
// 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 spaceList remove this comment once generating the final file
import Combine
import SwiftUI
struct SpaceListScreenCoordinatorParameters {
let userSession: UserSessionProtocol
}
enum SpaceListScreenCoordinatorAction {
case showSettings
}
final class SpaceListScreenCoordinator: CoordinatorProtocol {
private let parameters: SpaceListScreenCoordinatorParameters
private let viewModel: SpaceListScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<SpaceListScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<SpaceListScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(parameters: SpaceListScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = SpaceListScreenViewModel(userSession: parameters.userSession)
}
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 .showSettings:
actionsSubject.send(.showSettings)
}
}
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(SpaceListScreen(context: viewModel.context))
}
}

View File

@@ -0,0 +1,33 @@
//
// 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 SpaceListScreenViewModelAction {
case showSettings
}
struct SpaceListScreenViewState: BindableState {
let userID: String
var userDisplayName: String?
var userAvatarURL: URL?
var rooms: [HomeScreenRoom]
var joinedRoomsCount: Int
var bindings: SpaceListScreenViewStateBindings
var subtitle: String {
L10n.screenSpaceListDetails(L10n.commonSpaces(rooms.count), L10n.commonRooms(joinedRoomsCount))
}
}
struct SpaceListScreenViewStateBindings { }
enum SpaceListScreenViewAction {
case showSettings
}

View File

@@ -0,0 +1,47 @@
//
// 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 SpaceListScreenViewModelType = StateStoreViewModelV2<SpaceListScreenViewState, SpaceListScreenViewAction>
class SpaceListScreenViewModel: SpaceListScreenViewModelType, SpaceListScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<SpaceListScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<SpaceListScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(userSession: UserSessionProtocol) {
super.init(initialViewState: SpaceListScreenViewState(userID: userSession.clientProxy.userID,
rooms: [],
joinedRoomsCount: 0,
bindings: .init()),
mediaProvider: userSession.mediaProvider)
userSession.clientProxy.userAvatarURLPublisher
.receive(on: DispatchQueue.main)
.weakAssign(to: \.state.userAvatarURL, on: self)
.store(in: &cancellables)
userSession.clientProxy.userDisplayNamePublisher
.receive(on: DispatchQueue.main)
.weakAssign(to: \.state.userDisplayName, on: self)
.store(in: &cancellables)
}
// MARK: - Public
override func process(viewAction: SpaceListScreenViewAction) {
MXLog.info("View model: received view action: \(viewAction)")
switch viewAction {
case .showSettings:
actionsSubject.send(.showSettings)
}
}
}

View File

@@ -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 SpaceListScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<SpaceListScreenViewModelAction, Never> { get }
var context: SpaceListScreenViewModelType.Context { get }
}

View File

@@ -0,0 +1,101 @@
//
// 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 SpaceListScreen: View {
@Bindable var context: SpaceListScreenViewModel.Context
var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
header
}
}
.navigationTitle(L10n.screenSpaceListTitle)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
.bloom()
}
var header: some View {
VStack(spacing: 16) {
BigIcon(icon: \.spaceSolid)
VStack(spacing: 8) {
Text(L10n.screenSpaceListTitle)
.font(.compound.headingLGBold)
.foregroundStyle(.compound.textPrimary)
.multilineTextAlignment(.center)
Text(context.viewState.subtitle)
.font(.compound.bodyLG)
.foregroundStyle(.compound.textSecondary)
.multilineTextAlignment(.center)
}
Text(L10n.screenSpaceListDescription)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textPrimary)
.multilineTextAlignment(.center)
}
.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)
}
}
@ToolbarContentBuilder
var toolbar: some ToolbarContent {
ToolbarItem(placement: .navigationBarLeading) {
Button {
context.send(viewAction: .showSettings)
} label: {
LoadableAvatarImage(url: context.viewState.userAvatarURL,
name: context.viewState.userDisplayName,
contentID: context.viewState.userID,
avatarSize: .user(on: .home),
mediaProvider: context.mediaProvider)
.accessibilityIdentifier(A11yIdentifiers.homeScreen.userAvatar)
.compositingGroup()
}
.accessibilityLabel(L10n.commonSettings)
}
ToolbarItem(placement: .principal) {
// Hides the navigationTitle (which is set for the navigation stack label).
Text("").accessibilityHidden(true)
}
}
}
// MARK: - Previews
struct SpaceListScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel()
static var previews: some View {
NavigationStack {
SpaceListScreen(context: viewModel.context)
}
}
static func makeViewModel(counterValue: Int = 0) -> SpaceListScreenViewModel {
let clientProxy = ClientProxyMock(.init())
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
let viewModel = SpaceListScreenViewModel(userSession: userSession)
return viewModel
}
}

View File

@@ -875,6 +875,12 @@ extension PreviewTests {
}
}
func testSpaceListScreen() async throws {
for (index, preview) in SpaceListScreen_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testSplashScreen() async throws {
for (index, preview) in SplashScreen_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:60e71badaa8586cc67ae28fa888bf072e61bf8c547c708a8ec32461e33c86619
size 100453

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:77dfe5e4cc52f77c46891842a27fdd99cdf510c303009d87b4285cd575938309
size 108725

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:65416f910dc4c02a093fe7accc67117a32cc12d8a6a1bf26977e4493d8bb0d19
size 55676

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c6f1b42f4cd90cbedcc744b7c5b9794b7b84b51d0ad4d083bb5837d7a9afc142
size 70168

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2024 New Vector Ltd.
// Copyright 2022-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.

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2024 New Vector Ltd.
// Copyright 2022-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.

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2024 New Vector Ltd.
// Copyright 2022-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.

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2024 New Vector Ltd.
// Copyright 2022-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.

View File

@@ -1,5 +1,5 @@
//
// Copyright 2022-2024 New Vector Ltd.
// Copyright 2022-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.

View File

@@ -0,0 +1,33 @@
//
// Copyright 2022-2024 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 XCTest
@testable import ElementX
@MainActor
class SpaceListScreenViewModelTests: XCTestCase {
var viewModel: SpaceListScreenViewModelProtocol!
var context: SpaceListScreenViewModelType.Context {
viewModel.context
}
func testInitialState() {
setupViewModel()
XCTAssertTrue(context.viewState.rooms.isEmpty)
XCTAssertEqual(context.viewState.joinedRoomsCount, 0)
}
// MARK: - Helpers
private func setupViewModel() {
let clientProxy = ClientProxyMock(.init())
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
viewModel = SpaceListScreenViewModel(userSession: userSession)
}
}