From b474c9efe31ea1ad3f35d12f30a51eb5877d3ba6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 20 Jan 2025 19:07:11 +0200 Subject: [PATCH] Refactor the JoinRoom screen to take advantage of newer APIs and support more joinRule/membership combinations (i.e. invite required, restricted, banned) (#3685) - expose the full RoomPreview and RoomMembershipDetails through their own proxies - implement standard mocks for all the different combinations - converge on a single room info provider - rebuild all the previews - prioritise the preview data over the room one. --- ElementX.xcodeproj/project.pbxproj | 36 +++ .../Mocks/Generated/GeneratedMocks.swift | 44 +++- .../Sources/Mocks/RoomPreviewProxyMock.swift | 90 ++++++++ .../JoinRoomScreen/JoinRoomScreenModels.swift | 24 +- .../JoinRoomScreenViewModel.swift | 100 +++++---- .../JoinRoomScreen/View/JoinRoomScreen.swift | 212 ++++++++++-------- .../Sources/Services/Client/ClientProxy.swift | 42 +--- .../Services/Client/ClientProxyProtocol.swift | 16 +- .../Services/Room/KnockedRoomProxy.swift | 1 - .../Sources/Services/Room/RoomInfoProxy.swift | 3 + .../RoomMembershipDetailsProxy.swift | 13 ++ .../RoomMembershipDetailsProxyProtocol.swift | 14 ++ .../Room/RoomPreview/RoomPreviewProxy.swift | 35 +++ .../RoomPreviewProxyProtocol.swift | 14 ++ .../test_joinRoomScreen-iPad-en-GB.Banned.png | 3 + .../test_joinRoomScreen-iPad-en-GB.Invite.png | 3 - ...inRoomScreen-iPad-en-GB.InviteRequired.png | 3 + ...test_joinRoomScreen-iPad-en-GB.Invited.png | 3 + ...st_joinRoomScreen-iPad-en-GB.Joinable.png} | 0 ...t_joinRoomScreen-iPad-en-GB.Knockable.png} | 0 ...t_joinRoomScreen-iPad-en-GB.Restricted.png | 3 + ...test_joinRoomScreen-iPad-en-GB.Unknown.png | 4 +- ...test_joinRoomScreen-iPad-pseudo.Banned.png | 3 + ...test_joinRoomScreen-iPad-pseudo.Invite.png | 3 - ...nRoomScreen-iPad-pseudo.InviteRequired.png | 3 + ...est_joinRoomScreen-iPad-pseudo.Invited.png | 3 + ...t_joinRoomScreen-iPad-pseudo.Joinable.png} | 0 ..._joinRoomScreen-iPad-pseudo.Knockable.png} | 0 ..._joinRoomScreen-iPad-pseudo.Restricted.png | 3 + ...est_joinRoomScreen-iPad-pseudo.Unknown.png | 4 +- ..._joinRoomScreen-iPhone-16-en-GB.Banned.png | 3 + ..._joinRoomScreen-iPhone-16-en-GB.Invite.png | 3 - ...mScreen-iPhone-16-en-GB.InviteRequired.png | 3 + ...joinRoomScreen-iPhone-16-en-GB.Invited.png | 3 + ...inRoomScreen-iPhone-16-en-GB.Joinable.png} | 0 ...nRoomScreen-iPhone-16-en-GB.Knockable.png} | 0 ...nRoomScreen-iPhone-16-en-GB.Restricted.png | 3 + ...joinRoomScreen-iPhone-16-en-GB.Unknown.png | 4 +- ...joinRoomScreen-iPhone-16-pseudo.Banned.png | 3 + ...joinRoomScreen-iPhone-16-pseudo.Invite.png | 3 - ...Screen-iPhone-16-pseudo.InviteRequired.png | 3 + ...oinRoomScreen-iPhone-16-pseudo.Invited.png | 3 + ...nRoomScreen-iPhone-16-pseudo.Joinable.png} | 0 ...RoomScreen-iPhone-16-pseudo.Knockable.png} | 0 ...RoomScreen-iPhone-16-pseudo.Restricted.png | 3 + ...oinRoomScreen-iPhone-16-pseudo.Unknown.png | 4 +- .../JoinRoomScreenViewModelTests.swift | 20 +- .../Sources/RoomFlowCoordinatorTests.swift | 12 +- 48 files changed, 504 insertions(+), 248 deletions(-) create mode 100644 ElementX/Sources/Mocks/RoomPreviewProxyMock.swift create mode 100644 ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxy.swift create mode 100644 ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxyProtocol.swift create mode 100644 ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxy.swift create mode 100644 ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxyProtocol.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Banned.png delete mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.InviteRequired.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invited.png rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPad-en-GB.Join.png => test_joinRoomScreen-iPad-en-GB.Joinable.png} (100%) rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPad-en-GB.Knock.png => test_joinRoomScreen-iPad-en-GB.Knockable.png} (100%) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Restricted.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Banned.png delete mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.InviteRequired.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invited.png rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPad-pseudo.Join.png => test_joinRoomScreen-iPad-pseudo.Joinable.png} (100%) rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPad-pseudo.Knock.png => test_joinRoomScreen-iPad-pseudo.Knockable.png} (100%) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Restricted.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Banned.png delete mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.InviteRequired.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invited.png rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPhone-16-en-GB.Join.png => test_joinRoomScreen-iPhone-16-en-GB.Joinable.png} (100%) rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPhone-16-en-GB.Knock.png => test_joinRoomScreen-iPhone-16-en-GB.Knockable.png} (100%) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Restricted.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Banned.png delete mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.InviteRequired.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invited.png rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPhone-16-pseudo.Join.png => test_joinRoomScreen-iPhone-16-pseudo.Joinable.png} (100%) rename PreviewTests/Sources/__Snapshots__/PreviewTests/{test_joinRoomScreen-iPhone-16-pseudo.Knock.png => test_joinRoomScreen-iPhone-16-pseudo.Knockable.png} (100%) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Restricted.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index b0f197307..24d8de254 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 077CB230153E072C94B1E6C3 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */; }; 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */; }; 07F6382E29845D235BFA3308 /* DeactivateAccountScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */; }; + 0847D85F823B55A3E95D16CC /* RoomPreviewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */; }; 08547E55DD3686A84550996D /* SeparatorMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13F354AD441E2FD83DED89AF /* SeparatorMediaEventsTimelineView.swift */; }; 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC9104846487244648D32C6D /* AudioPlayerProtocol.swift */; }; 08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035177BCD8E8308B098AC3C2 /* WindowManager.swift */; }; @@ -255,6 +256,7 @@ 3113065AABBC14CEAE6843FA /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8774CF614849664B5B3C2A1 /* UserSessionFlowCoordinatorStateMachine.swift */; }; 3118D9ABFD4BE5A3492FF88A /* ElementCallConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC437C491EA6996513B1CEAB /* ElementCallConfiguration.swift */; }; 32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */; }; + 32F47002A331817F0E6BD7EB /* RoomMembershipDetailsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1434D5169F0EE319E226DA7F /* RoomMembershipDetailsProxyProtocol.swift */; }; 339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; }; 33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; 33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */; }; @@ -894,6 +896,7 @@ B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; }; B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */; }; B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; }; + B2FDF69AC0C316F12142F91A /* RoomMembershipDetailsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */; }; B31E5493C99381D4E204438B /* RoomTimelineControllerFactoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */; }; B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */; }; B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */; }; @@ -1042,6 +1045,7 @@ D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; }; D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; }; D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; }; + D2466C6BC8CAD8FADD7BF89B /* RoomPreviewProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */; }; D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */; }; D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; }; D29E046C1E3045E0346C479D /* RoomRolesAndPermissionsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */; }; @@ -1190,6 +1194,7 @@ F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; F2D5C0E1351DA7BD16867629 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */; }; + F2E580C0FBFBEFFE9D69893B /* RoomPreviewProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 739077686814E4EA339B1C83 /* RoomPreviewProxyProtocol.swift */; }; F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */; }; F38D32C1B0232AAFE6A0822C /* ExtensionLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */; }; F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */; }; @@ -1423,6 +1428,7 @@ 127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = ""; }; 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; + 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembershipDetailsProxy.swift; sourceTree = ""; }; 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_avatar_room.jpg; sourceTree = ""; }; 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; @@ -1431,6 +1437,7 @@ 13BE9781699FB510E9263192 /* AppSettingsHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsHook.swift; sourceTree = ""; }; 13F354AD441E2FD83DED89AF /* SeparatorMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorMediaEventsTimelineView.swift; sourceTree = ""; }; 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; + 1434D5169F0EE319E226DA7F /* RoomMembershipDetailsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembershipDetailsProxyProtocol.swift; sourceTree = ""; }; 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenModels.swift; sourceTree = ""; }; 1511B1DCECC0DC75EB267328 /* KnockRequestsListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreen.swift; sourceTree = ""; }; 1562EAF6231151A675BED7A9 /* RoomDirectorySearchScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenCoordinator.swift; sourceTree = ""; }; @@ -1822,6 +1829,7 @@ 6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = ""; }; 6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenCoordinator.swift; sourceTree = ""; }; 667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = ""; }; + 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxyMock.swift; sourceTree = ""; }; 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = ""; }; 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPropertiesExt.swift; sourceTree = ""; }; 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = ""; }; @@ -1875,6 +1883,7 @@ 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderProtocol.swift; sourceTree = ""; }; 7310D8DFE01AF45F0689C3AA /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = ""; }; 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportFlowCoordinator.swift; sourceTree = ""; }; + 739077686814E4EA339B1C83 /* RoomPreviewProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxyProtocol.swift; sourceTree = ""; }; 73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingComposer.swift; sourceTree = ""; }; 7447C0AD7EF302CD027D6230 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SAS.strings; sourceTree = ""; }; 7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -2485,6 +2494,7 @@ F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenCoordinator.swift; sourceTree = ""; }; F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = ""; }; F3C7252B3461D06175D975A4 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/SAS.strings; sourceTree = ""; }; + F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxy.swift; sourceTree = ""; }; F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenViewModel.swift; sourceTree = ""; }; F409D44C2E6BE50462E82F8A /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Localizable.strings"; sourceTree = ""; }; F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionMock.swift; sourceTree = ""; }; @@ -3193,6 +3203,7 @@ 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */, 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */, F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */, + 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */, FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */, D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */, F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */, @@ -3490,6 +3501,8 @@ 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */, 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */, 2C0F49BD446849654C0D24E0 /* RoomMember */, + 4DC0344D2EBD0AE5D71754A9 /* RoomMembershipDetails */, + 7FC3F8FA5EA765AC3B000F55 /* RoomPreview */, 70DABA39C844CA931B829395 /* RoomSummary */, ); path = Room; @@ -3704,6 +3717,15 @@ path = UnitTests; sourceTree = ""; }; + 4DC0344D2EBD0AE5D71754A9 /* RoomMembershipDetails */ = { + isa = PBXGroup; + children = ( + 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */, + 1434D5169F0EE319E226DA7F /* RoomMembershipDetailsProxyProtocol.swift */, + ); + path = RoomMembershipDetails; + sourceTree = ""; + }; 4EC4EBBC4F6885775F198875 /* Sources */ = { isa = PBXGroup; children = ( @@ -4443,6 +4465,15 @@ path = Replies; sourceTree = ""; }; + 7FC3F8FA5EA765AC3B000F55 /* RoomPreview */ = { + isa = PBXGroup; + children = ( + F3D94852AD5BB376CBCC3544 /* RoomPreviewProxy.swift */, + 739077686814E4EA339B1C83 /* RoomPreviewProxyProtocol.swift */, + ); + path = RoomPreview; + sourceTree = ""; + }; 7FF02C3DED8CD9890375D9FF /* View */ = { isa = PBXGroup; children = ( @@ -7342,6 +7373,8 @@ 8944548A684F1C837CEC47F4 /* RoomMembersListScreenModels.swift in Sources */, F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */, C4078364FD9FA00EA9D00A15 /* RoomMembersListScreenViewModelProtocol.swift in Sources */, + B2FDF69AC0C316F12142F91A /* RoomMembershipDetailsProxy.swift in Sources */, + 32F47002A331817F0E6BD7EB /* RoomMembershipDetailsProxyProtocol.swift in Sources */, D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */, 83B17A44D3E7E6DF22D9A2A4 /* RoomModerationRole.swift in Sources */, C9F5B48D15B9BCAE1F8D564E /* RoomNotificationModeProxy.swift in Sources */, @@ -7361,6 +7394,9 @@ 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */, 79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */, F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */, + 0847D85F823B55A3E95D16CC /* RoomPreviewProxy.swift in Sources */, + D2466C6BC8CAD8FADD7BF89B /* RoomPreviewProxyMock.swift in Sources */, + F2E580C0FBFBEFFE9D69893B /* RoomPreviewProxyProtocol.swift in Sources */, FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */, DC77E9DB2CFBE84A2BDF20C5 /* RoomRolesAndPermissionsFlowCoordinator.swift in Sources */, D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */, diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 55dcff2dc..8a5d62be6 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -3187,13 +3187,13 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { var roomPreviewForIdentifierViaReceivedArguments: (identifier: String, via: [String])? var roomPreviewForIdentifierViaReceivedInvocations: [(identifier: String, via: [String])] = [] - var roomPreviewForIdentifierViaUnderlyingReturnValue: Result! - var roomPreviewForIdentifierViaReturnValue: Result! { + var roomPreviewForIdentifierViaUnderlyingReturnValue: Result! + var roomPreviewForIdentifierViaReturnValue: Result! { get { if Thread.isMainThread { return roomPreviewForIdentifierViaUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { returnValue = roomPreviewForIdentifierViaUnderlyingReturnValue } @@ -3211,9 +3211,9 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } } } - var roomPreviewForIdentifierViaClosure: ((String, [String]) async -> Result)? + var roomPreviewForIdentifierViaClosure: ((String, [String]) async -> Result)? - func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result { + func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result { roomPreviewForIdentifierViaCallsCount += 1 roomPreviewForIdentifierViaReceivedArguments = (identifier: identifier, via: via) DispatchQueue.main.async { @@ -13416,6 +13416,15 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol, @unchecked Sendable { } var underlyingRole: RoomMemberRole! +} +class RoomMembershipDetailsProxyMock: RoomMembershipDetailsProxyProtocol, @unchecked Sendable { + var ownRoomMember: RoomMemberProxyProtocol { + get { return underlyingOwnRoomMember } + set(value) { underlyingOwnRoomMember = value } + } + var underlyingOwnRoomMember: RoomMemberProxyProtocol! + var senderRoomMember: RoomMemberProxyProtocol? + } class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol, @unchecked Sendable { var mode: RoomNotificationModeProxy { @@ -13429,6 +13438,31 @@ class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol, } var underlyingIsDefault: Bool! +} +class RoomPreviewProxyMock: RoomPreviewProxyProtocol, @unchecked Sendable { + var info: RoomPreviewInfoProxy { + get { return underlyingInfo } + set(value) { underlyingInfo = value } + } + var underlyingInfo: RoomPreviewInfoProxy! + var ownMembershipDetailsCallsCount = 0 + var ownMembershipDetailsCalled: Bool { + return ownMembershipDetailsCallsCount > 0 + } + + var ownMembershipDetails: RoomMembershipDetailsProxyProtocol? { + get async { + ownMembershipDetailsCallsCount += 1 + if let ownMembershipDetailsClosure = ownMembershipDetailsClosure { + return await ownMembershipDetailsClosure() + } else { + return underlyingOwnMembershipDetails + } + } + } + var underlyingOwnMembershipDetails: RoomMembershipDetailsProxyProtocol? + var ownMembershipDetailsClosure: (() async -> RoomMembershipDetailsProxyProtocol?)? + } class RoomProxyMock: RoomProxyProtocol, @unchecked Sendable { var id: String { diff --git a/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift b/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift new file mode 100644 index 000000000..547b427c6 --- /dev/null +++ b/ElementX/Sources/Mocks/RoomPreviewProxyMock.swift @@ -0,0 +1,90 @@ +// +// Copyright 2025 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +// Please see LICENSE files in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +extension RoomPreviewProxyMock { + struct Configuration { + var roomID = "1" + var canonicalAlias = "#3🌞problem:matrix.org" + var name = "The Three-Body Problem - 三体" + var topic = "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”" + var avatarURL = URL.mockMXCAvatar.absoluteString + var numJoinedMembers = UInt64(100) + var numActiveMembers = UInt64(100) + var roomType = RoomType.room + var membership: Membership? + var joinRule: JoinRule + } + + static var joinable: RoomPreviewProxyMock { + .init(.init(membership: nil, joinRule: .public)) + } + + static var restricted: RoomPreviewProxyMock { + .init(.init(membership: nil, joinRule: .restricted(rules: []))) + } + + static var inviteRequired: RoomPreviewProxyMock { + .init(.init(membership: nil, joinRule: .invite)) + } + + static func invited(roomID: String? = nil) -> RoomPreviewProxyMock { + if let roomID { + return .init(.init(roomID: roomID, membership: .invited, joinRule: .invite)) + } + + return .init(.init(membership: .invited, joinRule: .invite)) + } + + static var knockable: RoomPreviewProxyMock { + .init(.init(membership: nil, joinRule: .knock)) + } + + static var knockableRestricted: RoomPreviewProxyMock { + .init(.init(membership: nil, joinRule: .knockRestricted(rules: []))) + } + + static var knocked: RoomPreviewProxyMock { + .init(.init(membership: .knocked, joinRule: .knock)) + } + + static var banned: RoomPreviewProxyMock { + .init(.init(membership: .banned, joinRule: .public)) + } + + convenience init(_ configuration: RoomPreviewProxyMock.Configuration) { + self.init() + underlyingInfo = .init(roomPreviewInfo: .init(roomId: configuration.roomID, + canonicalAlias: configuration.canonicalAlias, + name: configuration.name, + topic: configuration.topic, + avatarUrl: configuration.avatarURL, + numJoinedMembers: configuration.numJoinedMembers, + numActiveMembers: configuration.numActiveMembers, + roomType: configuration.roomType, + isHistoryWorldReadable: nil, + membership: configuration.membership, + joinRule: configuration.joinRule, + isDirect: nil, + heroes: nil)) + + let roomMembershipDetails = RoomMembershipDetailsProxyMock() + + let mockMember = RoomMemberProxyMock() + mockMember.userID = "@bob:matrix.org" + mockMember.displayName = "Billy Bob" + mockMember.avatarURL = .mockMXCUserAvatar + mockMember.membershipChangeReason = "Ain't nobody need no reason" + + roomMembershipDetails.senderRoomMember = mockMember + roomMembershipDetails.ownRoomMember = mockMember + + underlyingOwnMembershipDetails = roomMembershipDetails + } +} diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift index cb4fae2ff..e79f73c3f 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift @@ -12,13 +12,16 @@ enum JoinRoomScreenViewModelAction { case dismiss } -enum JoinRoomScreenInteractionMode { +enum JoinRoomScreenMode: Equatable { case loading case unknown + case joinable + case restricted + case inviteRequired case invited - case join - case knock + case knockable case knocked + case banned(sender: String?, reason: String?) } struct JoinRoomScreenRoomDetails { @@ -31,12 +34,11 @@ struct JoinRoomScreenRoomDetails { } struct JoinRoomScreenViewState: BindableState { - // Maybe use room summary details or similar here?? let roomID: String var roomDetails: JoinRoomScreenRoomDetails? - var mode: JoinRoomScreenInteractionMode = .loading + var mode: JoinRoomScreenMode = .loading var bindings = JoinRoomScreenViewStateBindings() @@ -46,10 +48,14 @@ struct JoinRoomScreenViewState: BindableState { var subtitle: String? { switch mode { - case .loading: nil - case .unknown: L10n.screenJoinRoomSubtitleNoPreview - case .invited, .join, .knock: roomDetails?.canonicalAlias - case .knocked: nil + case .loading: + nil + case .unknown: + L10n.screenJoinRoomSubtitleNoPreview + case .knocked: + nil + default: + roomDetails?.canonicalAlias } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 99f564665..b73210ea1 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -17,7 +17,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo private let clientProxy: ClientProxyProtocol private let userIndicatorController: UserIndicatorControllerProtocol - private var roomPreviewDetails: RoomPreviewDetails? + private var roomPreview: RoomPreviewProxyProtocol? private var room: RoomProxyType? private let actionsSubject: PassthroughSubject = .init() @@ -72,22 +72,21 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo private func loadRoomDetails() async { showLoadingIndicator() - defer { - hideLoadingIndicator() - updateRoomDetails() - } - await updateRoom() switch await clientProxy.roomPreviewForIdentifier(roomID, via: via) { - case .success(let roomPreviewDetails): - self.roomPreviewDetails = roomPreviewDetails - updateRoomDetails() + case .success(let roomPreview): + self.roomPreview = roomPreview + await updateRoomDetails() case .failure(.roomPreviewIsPrivate): break // Handled by the mode, we don't need an error indicator. case .failure: userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown)) } + + hideLoadingIndicator() + + await updateRoomDetails() } private func updateRoom() async { @@ -97,58 +96,77 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo // take priority over the preview one. if let room = await clientProxy.roomForIdentifier(roomID) { self.room = room - updateRoomDetails() + await updateRoomDetails() } } - private func updateRoomDetails() { - var roomPreviewInfo: BaseRoomInfoProxyProtocol? + private func updateRoomDetails() async { + var roomInfo: BaseRoomInfoProxyProtocol? var inviter: RoomInviterDetails? switch room { case .joined(let joinedRoomProxy): - roomPreviewInfo = joinedRoomProxy.infoPublisher.value + roomInfo = joinedRoomProxy.infoPublisher.value case .invited(let invitedRoomProxy): inviter = invitedRoomProxy.inviter.map(RoomInviterDetails.init) - roomPreviewInfo = invitedRoomProxy.info + roomInfo = invitedRoomProxy.info case .knocked(let knockedRoomProxy): - roomPreviewInfo = knockedRoomProxy.info + roomInfo = knockedRoomProxy.info default: break } - - let name = roomPreviewInfo?.displayName ?? roomPreviewDetails?.name - state.roomDetails = JoinRoomScreenRoomDetails(name: name, - topic: roomPreviewInfo?.topic ?? roomPreviewDetails?.topic, - canonicalAlias: roomPreviewInfo?.canonicalAlias ?? roomPreviewDetails?.canonicalAlias, - avatar: roomPreviewInfo?.avatar ?? .room(id: roomID, name: name ?? "", avatarURL: roomPreviewDetails?.avatarURL), - memberCount: UInt(roomPreviewInfo?.activeMembersCount ?? Int(roomPreviewDetails?.memberCount ?? 0)), + + let info = roomPreview?.info ?? roomInfo + state.roomDetails = JoinRoomScreenRoomDetails(name: info?.displayName, + topic: info?.topic, + canonicalAlias: info?.canonicalAlias, + avatar: info?.avatar ?? .room(id: roomID, name: info?.displayName ?? "", avatarURL: nil), + memberCount: UInt(info?.activeMembersCount ?? 0), inviter: inviter) - updateMode() + await updateMode() } - private func updateMode() { - if case .knocked = room { - state.mode = .knocked + private func updateMode() async { + if roomPreview == nil, room == nil { + state.mode = .unknown return } - // Check invites first to show Accept/Decline buttons on public rooms. - if case .invited = room { - state.mode = .invited - return - } - - if roomPreviewDetails?.isInvited ?? false { - state.mode = .invited - return - } - - if roomPreviewDetails?.canKnock ?? false, appSettings.knockingEnabled { - state.mode = .knock - } else { - state.mode = .join + if let roomPreview { + let membershipDetails = await roomPreview.ownMembershipDetails + + switch roomPreview.info.membership { + case .invited: + state.mode = .invited + case .knocked: + state.mode = .knocked + case .banned: + state.mode = .banned(sender: membershipDetails?.senderRoomMember?.displayName ?? membershipDetails?.senderRoomMember?.userID, + reason: membershipDetails?.ownRoomMember.membershipChangeReason) + default: + switch roomPreview.info.joinRule { + case .private, .invite: + state.mode = .inviteRequired + case .knock, .knockRestricted: + state.mode = appSettings.knockingEnabled ? .knockable : .joinable + case .restricted: + state.mode = .restricted + default: + state.mode = .joinable + } + } + } else if let room { + switch room { + case .invited: + state.mode = .invited + case .knocked: + state.mode = .knocked + case .banned: + state.mode = .banned(sender: nil, reason: nil) + default: + state.mode = .joinable + } } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index e7b6bcb15..bf912d525 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -27,7 +27,7 @@ struct JoinRoomScreen: View { mainContent } } bottomContent: { - buttons + bottomContent } .alert(item: $context.alertInfo) .background() @@ -86,7 +86,7 @@ struct JoinRoomScreen: View { .lineLimit(3) } - if context.viewState.mode == .knock { + if context.viewState.mode == .knockable { knockMessage .padding(.top, 19) } @@ -148,27 +148,76 @@ struct JoinRoomScreen: View { } @ViewBuilder - var buttons: some View { + var bottomContent: some View { switch context.viewState.mode { - case .loading, .unknown: + case .loading: EmptyView() - case .knock: + case .joinable: + joinButton + case .unknown, .restricted: // If unknown, do our best. + VStack(spacing: 24) { + bottomNoticeMessage(L10n.screenJoinRoomJoinRestrictedMessage) + + joinButton + } + case .knockable: Button(L10n.screenJoinRoomKnockAction) { context.send(viewAction: .knock) } .buttonStyle(.compound(.super)) case .knocked: Button(L10n.screenJoinRoomCancelKnockAction) { context.send(viewAction: .cancelKnock) } .buttonStyle(.compound(.secondary)) - case .join: - Button(L10n.screenJoinRoomJoinAction) { context.send(viewAction: .join) } - .buttonStyle(.compound(.super)) + case .inviteRequired: + bottomNoticeMessage(L10n.screenJoinRoomInviteRequiredMessage) case .invited: ViewThatFits { HStack(spacing: 8) { inviteButtons } VStack(spacing: 16) { inviteButtons } } + case .banned(let sender, let reason): + if let sender, let reason { + bottomErrorMessage(title: L10n.screenJoinRoomBanByMessage(sender), + subtitle: L10n.screenJoinRoomBanReason(reason)) + } else { + bottomErrorMessage(title: L10n.screenJoinRoomBanMessage, subtitle: nil) + } } } + func bottomNoticeMessage(_ notice: String) -> some View { + Label(notice, icon: \.info) + .labelStyle(.custom(spacing: 12, alignment: .top)) + .font(.compound.bodyLGSemibold) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding() + .background(.compound.bgSubtleSecondary) + .cornerRadius(14, corners: .allCorners) + } + + func bottomErrorMessage(title: String, subtitle: String?) -> some View { + Label { + VStack(alignment: .leading, spacing: 4) { + Text(title) + .font(.compound.bodyLGSemibold) + .foregroundStyle(.compound.textCriticalPrimary) + + if let subtitle { + Text(subtitle) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textSecondary) + } + } + } icon: { + CompoundIcon(\.error) + .foregroundStyle(.compound.iconCriticalPrimary) + } + .labelStyle(.custom(spacing: 12, alignment: .top)) + .frame(maxWidth: .infinity, alignment: .leading) + .padding() + .background(.compound.bgSubtleSecondary) + .cornerRadius(14, corners: .allCorners) + } + @ViewBuilder var inviteButtons: some View { Button(L10n.actionDecline) { context.send(viewAction: .declineInvite) } @@ -177,6 +226,11 @@ struct JoinRoomScreen: View { .buttonStyle(.compound(.primary)) } + var joinButton: some View { + Button(L10n.screenJoinRoomJoinAction) { context.send(viewAction: .join) } + .buttonStyle(.compound(.super)) + } + @ToolbarContentBuilder private var toolbar: some ToolbarContent { if context.viewState.mode == .knocked { @@ -193,101 +247,75 @@ struct JoinRoomScreen: View { struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { static let unknownViewModel = makeViewModel(mode: .unknown) - static let knockViewModel = makeViewModel(mode: .knock) - static let joinViewModel = makeViewModel(mode: .join) - static let inviteViewModel = makeViewModel(mode: .invited) + static let joinableViewModel = makeViewModel(mode: .joinable) + static let restrictedViewModel = makeViewModel(mode: .restricted) + static let inviteRequiredViewModel = makeViewModel(mode: .inviteRequired) + static let invitedViewModel = makeViewModel(mode: .invited) + static let knockableViewModel = makeViewModel(mode: .knockable) static let knockedViewModel = makeViewModel(mode: .knocked) + static let bannedViewModel = makeViewModel(mode: .banned(sender: "Bob", reason: "Spamming")) static var previews: some View { - NavigationStack { - JoinRoomScreen(context: unknownViewModel.context) - } - .snapshotPreferences(expect: unknownViewModel.context.$viewState.map { state in - state.roomDetails != nil - }) - .previewDisplayName("Unknown") - - NavigationStack { - JoinRoomScreen(context: knockViewModel.context) - } - .snapshotPreferences(expect: knockViewModel.context.$viewState.map { state in - state.roomDetails != nil - }) - .previewDisplayName("Knock") - - NavigationStack { - JoinRoomScreen(context: joinViewModel.context) - } - .snapshotPreferences(expect: joinViewModel.context.$viewState.map { state in - state.roomDetails != nil - }) - .previewDisplayName("Join") - - NavigationStack { - JoinRoomScreen(context: inviteViewModel.context) - } - .snapshotPreferences(expect: inviteViewModel.context.$viewState.map { state in - state.roomDetails != nil - }) - .previewDisplayName("Invite") - - NavigationStack { - JoinRoomScreen(context: knockedViewModel.context) - } - .snapshotPreferences(expect: knockedViewModel.context.$viewState.map { state in - state.roomDetails != nil - }) - .previewDisplayName("Knocked") + makePreview(viewModel: unknownViewModel, previewDisplayName: "Unknown") + makePreview(viewModel: joinableViewModel, previewDisplayName: "Joinable") + makePreview(viewModel: restrictedViewModel, previewDisplayName: "Restricted") + makePreview(viewModel: inviteRequiredViewModel, previewDisplayName: "InviteRequired") + makePreview(viewModel: invitedViewModel, previewDisplayName: "Invited") + makePreview(viewModel: knockableViewModel, previewDisplayName: "Knockable") + makePreview(viewModel: knockedViewModel, previewDisplayName: "Knocked") + makePreview(viewModel: bannedViewModel, previewDisplayName: "Banned") } - static func makeViewModel(mode: JoinRoomScreenInteractionMode) -> JoinRoomScreenViewModel { + static func makePreview(viewModel: JoinRoomScreenViewModel, previewDisplayName: String) -> some View { + NavigationStack { + JoinRoomScreen(context: viewModel.context) + } + .snapshotPreferences(expect: viewModel.context.$viewState.map { state in + state.roomDetails != nil + }) + .previewDisplayName(previewDisplayName) + } + + static func makeViewModel(mode: JoinRoomScreenMode) -> JoinRoomScreenViewModel { + ServiceLocator.shared.settings.knockingEnabled = true + let clientProxy = ClientProxyMock(.init()) - // swiftlint:disable:next large_tuple - let membership: (isJoined: Bool, isInvited: Bool, isPublic: Bool, canKnock: Bool) = switch mode { - case .loading, .unknown: - (false, false, false, false) - case .invited: - (false, true, false, false) - case .join: - (false, false, true, false) - case .knock: - (false, false, false, true) - case .knocked: - (false, false, false, false) - } - - if mode == .unknown { + switch mode { + case .unknown: clientProxy.roomPreviewForIdentifierViaReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) - } else { - switch mode { - case .knocked: - clientProxy.roomForIdentifierClosure = { _ in - .knocked(KnockedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) - } - case .invited: - clientProxy.roomForIdentifierClosure = { _ in - .invited(InvitedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) - } - default: - break + clientProxy.roomForIdentifierReturnValue = nil + case .joinable: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.joinable) + clientProxy.roomForIdentifierReturnValue = nil + case .restricted: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.restricted) + clientProxy.roomForIdentifierReturnValue = nil + case .inviteRequired: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.inviteRequired) + clientProxy.roomForIdentifierReturnValue = nil + case .invited: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.invited()) + clientProxy.roomForIdentifierClosure = { _ in + .invited(InvitedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) } - clientProxy.roomPreviewForIdentifierViaReturnValue = .success(.init(roomID: "1", - name: "The Three-Body Problem - 三体", - canonicalAlias: "#3🌞problem:matrix.org", - // swiftlint:disable:next line_length - topic: "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”", - avatarURL: .mockMXCAvatar, - memberCount: UInt(100), - isHistoryWorldReadable: nil, - isJoined: membership.isJoined, - isInvited: membership.isInvited, - isPublic: membership.isPublic, - canKnock: membership.canKnock)) + case .knockable: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.knockable) + clientProxy.roomForIdentifierReturnValue = nil + case .knocked: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.knocked) + clientProxy.roomForIdentifierClosure = { _ in + .knocked(KnockedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) + } + case .banned: + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.banned) + clientProxy.roomForIdentifierClosure = { _ in + .banned + } + default: + break } - ServiceLocator.shared.settings.knockingEnabled = true - return JoinRoomScreenViewModel(roomID: "1", via: [], appSettings: ServiceLocator.shared.settings, diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 42a425f4a..276f41309 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -516,11 +516,10 @@ class ClientProxy: ClientProxyProtocol { return await buildRoomForIdentifier(identifier) } - func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result { + func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result { do { let roomPreview = try await client.getRoomPreviewFromRoomId(roomId: identifier, viaServers: via) - let roomPreviewInfo = try roomPreview.info() - return .success(.init(roomPreviewInfo)) + return try .success(RoomPreviewProxy(roomPreview: roomPreview)) } catch let error as ClientError where error.code == .forbidden { return .failure(.roomPreviewIsPrivate) } catch { @@ -1155,40 +1154,3 @@ private class SendQueueRoomErrorListenerProxy: SendQueueRoomErrorListener { onErrorClosure(roomId, error) } } - -private extension RoomPreviewDetails { - init(_ roomPreviewInfo: RoomPreviewInfo) { - self = RoomPreviewDetails(roomID: roomPreviewInfo.roomId, - name: roomPreviewInfo.name, - canonicalAlias: roomPreviewInfo.canonicalAlias, - topic: roomPreviewInfo.topic, - avatarURL: roomPreviewInfo.avatarUrl.flatMap(URL.init(string:)), - memberCount: UInt(roomPreviewInfo.numJoinedMembers), - isHistoryWorldReadable: roomPreviewInfo.isHistoryWorldReadable ?? false, - isJoined: roomPreviewInfo.membership == .joined, - isInvited: roomPreviewInfo.membership == .invited, - isPublic: roomPreviewInfo.isPublic, - canKnock: roomPreviewInfo.canKnock) - } -} - -private extension RoomPreviewInfo { - var canKnock: Bool { - switch joinRule { - case .knock, .knockRestricted: - return true - default: - return false - } - } - - var isPublic: Bool { - switch joinRule { - // for restricted rooms we want to show optimistically that the we may be able to join the room - case .public, .restricted: - return true - default: - return false - } - } -} diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 088d0df17..68460e4e1 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -61,20 +61,6 @@ enum SessionVerificationState { case unverified } -struct RoomPreviewDetails { - let roomID: String - let name: String? - let canonicalAlias: String? - let topic: String? - let avatarURL: URL? - let memberCount: UInt - let isHistoryWorldReadable: Bool? - let isJoined: Bool - let isInvited: Bool - let isPublic: Bool - let canKnock: Bool -} - // sourcery: AutoMockable protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var actionsPublisher: AnyPublisher { get } @@ -154,7 +140,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func roomForIdentifier(_ identifier: String) async -> RoomProxyType? - func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result + func roomPreviewForIdentifier(_ identifier: String, via: [String]) async -> Result @discardableResult func loadUserDisplayName() async -> Result diff --git a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift index 688afe277..9067d20e4 100644 --- a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift @@ -7,7 +7,6 @@ import Foundation import MatrixRustSDK -import UIKit class KnockedRoomProxy: KnockedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol diff --git a/ElementX/Sources/Services/Room/RoomInfoProxy.swift b/ElementX/Sources/Services/Room/RoomInfoProxy.swift index 75924b850..80233db1e 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxy.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxy.swift @@ -113,6 +113,9 @@ struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol { var isSpace: Bool { roomPreviewInfo.roomType == .space } var activeMembersCount: Int { Int(roomPreviewInfo.numActiveMembers ?? roomPreviewInfo.numJoinedMembers) } + var joinRule: JoinRule { roomPreviewInfo.joinRule } + var membership: Membership? { roomPreviewInfo.membership } + /// The room's avatar info for use in a ``RoomAvatarImage``. var avatar: RoomAvatar { if isDirect, avatarURL == nil { diff --git a/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxy.swift b/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxy.swift new file mode 100644 index 000000000..5b266db1a --- /dev/null +++ b/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxy.swift @@ -0,0 +1,13 @@ +// +// Copyright 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 Foundation + +struct RoomMembershipDetailsProxy: RoomMembershipDetailsProxyProtocol { + let ownRoomMember: RoomMemberProxyProtocol + let senderRoomMember: RoomMemberProxyProtocol? +} diff --git a/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxyProtocol.swift new file mode 100644 index 000000000..13449c821 --- /dev/null +++ b/ElementX/Sources/Services/Room/RoomMembershipDetails/RoomMembershipDetailsProxyProtocol.swift @@ -0,0 +1,14 @@ +// +// Copyright 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 Foundation + +// sourcery: AutoMockable +protocol RoomMembershipDetailsProxyProtocol { + var ownRoomMember: RoomMemberProxyProtocol { get } + var senderRoomMember: RoomMemberProxyProtocol? { get } +} diff --git a/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxy.swift b/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxy.swift new file mode 100644 index 000000000..41e15661e --- /dev/null +++ b/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxy.swift @@ -0,0 +1,35 @@ +// +// Copyright 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 MatrixRustSDK + +final class RoomPreviewProxy: RoomPreviewProxyProtocol { + private let roomPreview: RoomPreview + + let info: RoomPreviewInfoProxy + + init(roomPreview: RoomPreview) throws { + self.roomPreview = roomPreview + info = try .init(roomPreviewInfo: roomPreview.info()) + } + + var ownMembershipDetails: RoomMembershipDetailsProxyProtocol? { + get async { + guard let details = await roomPreview.ownMembershipDetails() else { + return nil + } + + var senderRoomMember: RoomMemberProxy? + if let member = details.senderRoomMember { + senderRoomMember = .init(member: member) + } + + return RoomMembershipDetailsProxy(ownRoomMember: RoomMemberProxy(member: details.ownRoomMember), + senderRoomMember: senderRoomMember) + } + } +} diff --git a/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxyProtocol.swift new file mode 100644 index 000000000..72a3386ec --- /dev/null +++ b/ElementX/Sources/Services/Room/RoomPreview/RoomPreviewProxyProtocol.swift @@ -0,0 +1,14 @@ +// +// Copyright 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 Foundation + +// sourcery: AutoMockable +protocol RoomPreviewProxyProtocol { + var info: RoomPreviewInfoProxy { get } + var ownMembershipDetails: RoomMembershipDetailsProxyProtocol? { get async } +} diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Banned.png new file mode 100644 index 000000000..da6576e97 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed8e2b415bb4fac216f7e9949f736c2001b9bfc8aa112e6867e4c9419b16ba22 +size 177624 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png deleted file mode 100644 index 4244a8a64..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1645515771a470a87b2a6bce077fd4605cbc1bef9eaf5443568b5df90c2de311 -size 176707 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.InviteRequired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.InviteRequired.png new file mode 100644 index 000000000..61f0bf8d4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.InviteRequired.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46d4db4ce035ccecd1f36555844bd7b36b9870b961a63e78ba8fd55524a97182 +size 168841 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invited.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invited.png new file mode 100644 index 000000000..c0583e029 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invited.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebc89ecca286720e20459176eb056e8cbdef378ec43650fe0ce3dca536d453f9 +size 177783 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Joinable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Joinable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knockable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knockable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Restricted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Restricted.png new file mode 100644 index 000000000..66890ed2c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Restricted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:730cc42657835ecc027ec83ec50f8ee2eb7715d7f24a17fa5c7208fa0245dfd9 +size 192443 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png index 03bbbde88..959bdff28 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Unknown.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3df84c0006286d66189c53154fe3ae17acb53b21122ea7893bf3034e8b3654c -size 98431 +oid sha256:0f3662b03552af1d87d057db781d116590d37ea66803b13d5c727581c6510c58 +size 123643 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Banned.png new file mode 100644 index 000000000..ce390d07c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6810a99b9515b741e07c200469e90067df19b3988fd961a3515496da22dc46bc +size 187166 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png deleted file mode 100644 index 95067ec74..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c24082811d674e78690542d5ad4447fae4028a1b7d6e3b7182ce348f0422e1bd -size 181607 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.InviteRequired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.InviteRequired.png new file mode 100644 index 000000000..d89940419 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.InviteRequired.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2cc59fc58138ac6f3d81ab99ae2675b27757c5a7cc4d8ea7cd95f0bbbc701cd +size 175215 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invited.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invited.png new file mode 100644 index 000000000..5e89b4a1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invited.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fe746b5db709ed299b4340566ee6a48cc20237dc3b9b2c2923c1de78903f7f4 +size 182572 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Joinable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Joinable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knockable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knockable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Restricted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Restricted.png new file mode 100644 index 000000000..0d4411fe0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Restricted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87b5aaf1f670f1b424d88c531772596a4bec39b2a9fe9ecbb4f9db4be25cd705 +size 203750 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png index c89239f29..8c91aca52 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Unknown.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b2b16b80f6f6d362c28f385b7bb55343a108494ec10a1204f92f8e224e971e7 -size 101218 +oid sha256:8a4ed3ec9a4b6c75c2a071c7896295fb12dc320832274a71a6ad70734b85edad +size 144830 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Banned.png new file mode 100644 index 000000000..be378c322 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d981af0fe2d6c26179627dc23ee23a8d1c2565d4214c770a440c1b1b63a1b0d +size 124023 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png deleted file mode 100644 index 0aa8d7e08..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf9575beca228f4ed808a40f5fab5cc49ff3e14b8d4b25bfd5d24bf69a12cb89 -size 121706 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.InviteRequired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.InviteRequired.png new file mode 100644 index 000000000..7438dd40f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.InviteRequired.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f3d7c7aa395cd67be31942f8b80d764039f95ec7071b0796e0dee27e23e2aeb +size 116366 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invited.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invited.png new file mode 100644 index 000000000..11e0b4f6f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invited.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c7599e77de7e4b067d4be8ed3475c6f13e2ebc890eba7da767ebb7be39d5839 +size 122089 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Joinable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Joinable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knockable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knockable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Restricted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Restricted.png new file mode 100644 index 000000000..f5c7651fb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Restricted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c8a83efc1c0466a1a35246edf00eac29819d53d8a3175e135b59118588a14eb +size 134920 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png index 45ca02645..e6b79dad7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Unknown.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e61e6e702aac228161a0432be400886ba361c0d8888fbb3b7009d0522aeb4112 -size 51837 +oid sha256:6b2b096f3f25e4207427a7112773126dc38b9596dd7bd4f1f2f2c6b60cea3472 +size 80107 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Banned.png new file mode 100644 index 000000000..357ef4fbf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Banned.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e80d687a41d05adf71953222cd746efce17bc6a24ad7b2ec2ec8304df24a8c4 +size 136385 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png deleted file mode 100644 index 7110aa501..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46731b3bef32a06409ed48eb4b2311a396def898d24c92d7e17c0d289e0a292a -size 128657 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.InviteRequired.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.InviteRequired.png new file mode 100644 index 000000000..822042dc1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.InviteRequired.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6ef69abb4af5cd05c98801bf75d16f113c9de2b075a37195c1e1dd81d18ec16 +size 124936 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invited.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invited.png new file mode 100644 index 000000000..94e0157c0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invited.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a93efd02d0b494fd2f12b28a0ca032e0e454c05470180afabf7188482d91254 +size 129056 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Joinable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Joinable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knockable.png similarity index 100% rename from PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png rename to PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knockable.png diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Restricted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Restricted.png new file mode 100644 index 000000000..7f6e6bebc --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Restricted.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6458f0d09edc8692ab962a81a0b8b56b189fa2336381fcf0244d810f0f37260 +size 150232 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png index 197de9e10..db52caf03 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Unknown.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b820eab5aba492d8a78e37464bb6475fcf41bfe0c5a15f2deceb9b57cfe14ca -size 58259 +oid sha256:25e0625bdd58ec7e81991174fe1ef8e0e7a75bfddb41fd31bcfd03d514c3a1ef +size 109065 diff --git a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift index 18d1b0ab6..fc1e2541e 100644 --- a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift +++ b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift @@ -74,33 +74,25 @@ class JoinRoomScreenViewModelTests: XCTestCase { } private func setupViewModel(throwing: Bool = false, knocked: Bool = false) { + ServiceLocator.shared.settings.knockingEnabled = true + let clientProxy = ClientProxyMock(.init()) clientProxy.joinRoomViaReturnValue = throwing ? .failure(.sdkError(ClientProxyMockError.generic)) : .success(()) - clientProxy.roomPreviewForIdentifierViaReturnValue = .success(.init(roomID: "", - name: nil, - canonicalAlias: nil, - topic: nil, - avatarURL: nil, - memberCount: 0, - isHistoryWorldReadable: nil, - isJoined: false, - isInvited: false, - isPublic: false, - canKnock: false)) - if knocked { + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.knocked) + clientProxy.roomForIdentifierClosure = { _ in let roomProxy = KnockedRoomProxyMock(.init()) // to test the cancel knock function roomProxy.cancelKnockUnderlyingReturnValue = .success(()) return .knocked(roomProxy) } + } else { + clientProxy.roomPreviewForIdentifierViaReturnValue = .success(RoomPreviewProxyMock.joinable) } - ServiceLocator.shared.settings.knockingEnabled = true - viewModel = JoinRoomScreenViewModel(roomID: "1", via: [], appSettings: ServiceLocator.shared.settings, diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 47c380e16..c3ea9b9f1 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -316,17 +316,7 @@ class RoomFlowCoordinatorTests: XCTestCase { clientProxy.roomPreviewForIdentifierViaClosure = { [roomType] roomID, _ in switch roomType { case .invited: - return .success(.init(roomID: roomID, - name: "Invite", - canonicalAlias: nil, - topic: nil, - avatarURL: nil, - memberCount: 0, - isHistoryWorldReadable: nil, - isJoined: false, - isInvited: true, - isPublic: false, - canKnock: false)) + return .success(RoomPreviewProxyMock.invited(roomID: roomID)) default: fatalError("Something isn't set up right") }