From 2511c98090cc22865d5ff737c7bbd7884f70bf4d Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:23:06 +0200 Subject: [PATCH] Knocked Preview implementation (#3426) * JoinRoomScreen ui for knocking * code improvement * updated previews * added knocked state with tests * send knock request * Apply suggestions from code review Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * pr comments * update tests * new API * knock implementation and cancel knock * update strings * added a knocked cell in the home screen * design update * updated SDK * simplified the invite case code * pr comments * updated previews * added message as reason * updated strings * fixing tests --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- ElementX.xcodeproj/project.pbxproj | 16 +- .../en.lproj/Localizable.strings | 7 +- ElementX/Sources/Generated/Strings.swift | 12 +- .../Sources/Mocks/InvitedRoomProxyMock.swift | 31 +++ .../Mocks/RoomSummaryProviderMock.swift | 27 +-- .../SwiftUI/Views}/RoomHeaderView.swift | 0 .../Screens/HomeScreen/HomeScreenModels.swift | 30 ++- .../View/HomeScreenInviteCell.swift | 9 +- .../View/HomeScreenKnockedCell.swift | 200 ++++++++++++++++++ .../HomeScreen/View/HomeScreenRoomList.swift | 2 + .../JoinRoomScreenCoordinator.swift | 2 +- .../JoinRoomScreen/JoinRoomScreenModels.swift | 3 +- .../JoinRoomScreenViewModel.swift | 61 ++++-- .../JoinRoomScreen/View/JoinRoomScreen.swift | 34 ++- .../Sources/Services/Client/ClientProxy.swift | 4 +- .../Services/Room/KnockedRoomProxy.swift | 8 +- .../Room/RoomSummary/RoomSummary.swift | 27 ++- .../RoomSummary/RoomSummaryProvider.swift | 9 +- .../Timeline/TimelineProxyProtocol.swift | 1 - .../Sources/GeneratedPreviewTests.swift | 6 + ...est_homeScreenKnockedCell-iPad-en-GB.1.png | 3 + ...st_homeScreenKnockedCell-iPad-pseudo.1.png | 3 + ...omeScreenKnockedCell-iPhone-16-en-GB.1.png | 3 + ...meScreenKnockedCell-iPhone-16-pseudo.1.png | 3 + .../test_joinRoomScreen-iPad-en-GB.Invite.png | 4 +- .../test_joinRoomScreen-iPad-en-GB.Join.png | 4 +- .../test_joinRoomScreen-iPad-en-GB.Knock.png | 4 +- ...test_joinRoomScreen-iPad-en-GB.Knocked.png | 4 +- ...test_joinRoomScreen-iPad-en-GB.Unknown.png | 4 +- ...test_joinRoomScreen-iPad-pseudo.Invite.png | 4 +- .../test_joinRoomScreen-iPad-pseudo.Join.png | 4 +- .../test_joinRoomScreen-iPad-pseudo.Knock.png | 4 +- ...est_joinRoomScreen-iPad-pseudo.Knocked.png | 4 +- ...est_joinRoomScreen-iPad-pseudo.Unknown.png | 4 +- ..._joinRoomScreen-iPhone-16-en-GB.Invite.png | 4 +- ...st_joinRoomScreen-iPhone-16-en-GB.Join.png | 4 +- ...t_joinRoomScreen-iPhone-16-en-GB.Knock.png | 4 +- ...joinRoomScreen-iPhone-16-en-GB.Knocked.png | 4 +- ...joinRoomScreen-iPhone-16-en-GB.Unknown.png | 4 +- ...joinRoomScreen-iPhone-16-pseudo.Invite.png | 4 +- ...t_joinRoomScreen-iPhone-16-pseudo.Join.png | 4 +- ..._joinRoomScreen-iPhone-16-pseudo.Knock.png | 4 +- ...oinRoomScreen-iPhone-16-pseudo.Knocked.png | 4 +- ...oinRoomScreen-iPhone-16-pseudo.Unknown.png | 4 +- UnitTests/Sources/HomeScreenRoomTests.swift | 3 +- .../JoinRoomScreenViewModelTests.swift | 22 +- UnitTests/Sources/LoggingTests.swift | 3 +- UnitTests/Sources/RoomSummaryTests.swift | 3 +- 48 files changed, 492 insertions(+), 120 deletions(-) create mode 100644 ElementX/Sources/Mocks/InvitedRoomProxyMock.swift rename ElementX/Sources/{Screens/RoomScreen/View => Other/SwiftUI/Views}/RoomHeaderView.swift (100%) create mode 100644 ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 07e8e2e7e..1d2e485bd 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -34,7 +34,6 @@ 03CDCA6243F89B194E3FAD17 /* EncryptionAuthenticity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955336CBD5ED73C792D1F580 /* EncryptionAuthenticity.swift */; }; 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */; }; 044DD8F80231BC30570F7965 /* UserDiscoveryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AAD845E53B0C8B5E0812C2 /* UserDiscoveryService.swift */; }; - 04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422724361B6555364C43281E /* RoomHeaderView.swift */; }; 04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */; }; 053B8BD2496207838878C6C9 /* PinnedItemsBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C9BAE9F9436B14E4E22E8F /* PinnedItemsBannerView.swift */; }; 059173B3C77056C406906B6D /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = D4DA544B2520BFA65D6DB4BB /* target.yml */; }; @@ -46,6 +45,7 @@ 06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */; }; 06F8EDF52E33A2D36BCC1161 /* AppLockScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D6F88FE35A0979D2821E06 /* AppLockScreen.swift */; }; 071A017E415AD378F2961B11 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227AC5D71A4CE43512062243 /* URL.swift */; }; + 07376A5274822EB45CC320C7 /* InvitedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A21027F05874B1BCC3E452B /* InvitedRoomProxyMock.swift */; }; 07756D532EFE33DD1FA258E5 /* GeoURITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */; }; 077CB230153E072C94B1E6C3 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */; }; 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */; }; @@ -611,6 +611,7 @@ 865DD5CA474C6AE6C2BC008E /* NetworkMonitorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */; }; 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; + 86DFA58FBBEB0AF671D2A1E1 /* HomeScreenKnockedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A103580EBA06155B1343EF16 /* HomeScreenKnockedCell.swift */; }; 86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */; }; 872A6457DF573AF8CEAE927A /* LoginHomeserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */; }; 874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */; }; @@ -716,6 +717,7 @@ 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; }; 9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; }; 9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; }; + 9C63171267E22FEB288EC860 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1627F2D56477BD331F6D732C /* RoomHeaderView.swift */; }; 9CBB04365408F9D6F46BA3A7 /* PinnedEventsTimelineFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */; }; 9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; }; 9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; }; @@ -1301,6 +1303,7 @@ 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorProtocol.swift; sourceTree = ""; }; 15A657D96779D1DEB8EF1327 /* CreateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModel.swift; sourceTree = ""; }; 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = ""; }; + 1627F2D56477BD331F6D732C /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.swift; sourceTree = ""; }; 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = ""; }; 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = ""; }; 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = ""; }; @@ -1465,6 +1468,7 @@ 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = ""; }; 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerMock.swift; sourceTree = ""; }; 3A12D3D8138F1B71AFA7C858 /* CompletionSuggestionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionService.swift; sourceTree = ""; }; + 3A21027F05874B1BCC3E452B /* InvitedRoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitedRoomProxyMock.swift; sourceTree = ""; }; 3AD253E7EFF88F308D644272 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/SAS.strings"; sourceTree = ""; }; 3B5E97E9615A158C76B2AB77 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; 3BAC027034248429A438886B /* AppMediatorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediatorMock.swift; sourceTree = ""; }; @@ -1504,7 +1508,6 @@ 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = ""; }; 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayoutLabelStyle.swift; sourceTree = ""; }; - 422724361B6555364C43281E /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.swift; sourceTree = ""; }; 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = ""; }; 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = ""; }; 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenModels.swift; sourceTree = ""; }; @@ -1901,6 +1904,7 @@ A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = ""; }; A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = ""; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = ""; }; + A103580EBA06155B1343EF16 /* HomeScreenKnockedCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenKnockedCell.swift; sourceTree = ""; }; A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerProtocol.swift; sourceTree = ""; }; A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelProtocol.swift; sourceTree = ""; }; A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenCoordinator.swift; sourceTree = ""; }; @@ -2915,6 +2919,7 @@ 4E600B315B920B9687F8EE1B /* ComposerDraftServiceMock.swift */, E321E840DCC63790049984F4 /* ElementCallServiceMock.swift */, 1B10423B9102086A2D9BFCBA /* EventTimelineItem.swift */, + 3A21027F05874B1BCC3E452B /* InvitedRoomProxyMock.swift */, 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */, 9E8F4D7D61B80EBD5CB92F8A /* KnockedRoomProxyMock.swift */, 6F65E4BB9E82EB8373207CF8 /* MediaProviderMock.swift */, @@ -2964,6 +2969,7 @@ 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */, C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */, BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */, + 1627F2D56477BD331F6D732C /* RoomHeaderView.swift */, 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */, 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */, DE7C80EF77AD102053D3646E /* RoundedLabelItem.swift */, @@ -3425,6 +3431,7 @@ A3B4B58B79A6FA250B24A1EC /* HomeScreenContent.swift */, C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */, D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */, + A103580EBA06155B1343EF16 /* HomeScreenKnockedCell.swift */, 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */, ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */, C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */, @@ -4036,7 +4043,6 @@ 79023E5904B155E8E2B8B502 /* View */ = { isa = PBXGroup; children = ( - 422724361B6555364C43281E /* RoomHeaderView.swift */, 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */, 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */, 4552D3466B1453F287223ADA /* SwipeRightAction.swift */, @@ -6501,6 +6507,7 @@ 8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */, 77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */, 22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */, + 86DFA58FBBEB0AF671D2A1E1 /* HomeScreenKnockedCell.swift in Sources */, 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */, B04E9EB589CE99C3929E817A /* HomeScreenRecoveryKeyConfirmationBanner.swift in Sources */, 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */, @@ -6532,6 +6539,7 @@ F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */, A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */, 89B909AC66B96FA054EF3C14 /* InvitedRoomProxy.swift in Sources */, + 07376A5274822EB45CC320C7 /* InvitedRoomProxyMock.swift in Sources */, 6A54F52443EC52AC5CD772C0 /* JoinRoomScreen.swift in Sources */, AFE2AB612A1460E49578D746 /* JoinRoomScreenCoordinator.swift in Sources */, DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */, @@ -6770,7 +6778,7 @@ 2814E7075BF3A5C0CCBC9F90 /* RoomDirectorySearchView.swift in Sources */, 42F1C8731166633E35A6D7E6 /* RoomEventStringBuilder.swift in Sources */, D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */, - 04A16B45228F7678A027C079 /* RoomHeaderView.swift in Sources */, + 9C63171267E22FEB288EC860 /* RoomHeaderView.swift in Sources */, 8A83D715940378B9BA9F739E /* RoomInviterLabel.swift in Sources */, F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */, 4A9CEEE612D6D8B3DDBD28BA /* RoomListFilterView.swift in Sources */, diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 6e49740a0..4aeb3bef7 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -371,6 +371,7 @@ "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; +"screen_roomlist_knock_event_sent_description" = "Request to join sent"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -822,12 +823,16 @@ "screen_session_verification_open_existing_session_title" = "Open an existing session"; "screen_session_verification_positive_button_canceled" = "Retry verification"; "screen_session_verification_positive_button_initial" = "I am ready"; -"screen_session_verification_positive_button_verifying_ongoing" = "Waiting to match"; +"screen_session_verification_positive_button_verifying_ongoing" = "Waiting to match…"; "screen_session_verification_ready_subtitle" = "Compare a unique set of emojis."; "screen_session_verification_request_accepted_subtitle" = "Compare the unique emoji, ensuring they appear in the same order."; "screen_session_verification_request_details_timestamp" = "Signed in"; +"screen_session_verification_request_failure_subtitle" = "Either the request timed out, the request was denied, or there was a verification mismatch."; +"screen_session_verification_request_failure_title" = "Verification failed"; "screen_session_verification_request_footer" = "Only continue if you initiated this verification."; "screen_session_verification_request_subtitle" = "Verify the other device to keep your message history secure."; +"screen_session_verification_request_success_subtitle" = "Now you can read or send messages securely on your other device."; +"screen_session_verification_request_success_title" = "Device verified"; "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "They don’t match"; "screen_session_verification_they_match" = "They match"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 2439a4346..a9fef6619 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1965,6 +1965,8 @@ internal enum L10n { /// Congrats! /// You don’t have any unread messages! internal static var screenRoomlistFilterUnreadsEmptyStateTitle: String { return L10n.tr("Localizable", "screen_roomlist_filter_unreads_empty_state_title") } + /// Request to join sent + internal static var screenRoomlistKnockEventSentDescription: String { return L10n.tr("Localizable", "screen_roomlist_knock_event_sent_description") } /// Chats internal static var screenRoomlistMainSpaceTitle: String { return L10n.tr("Localizable", "screen_roomlist_main_space_title") } /// Mark as read @@ -2013,7 +2015,7 @@ internal enum L10n { internal static var screenSessionVerificationPositiveButtonCanceled: String { return L10n.tr("Localizable", "screen_session_verification_positive_button_canceled") } /// I am ready internal static var screenSessionVerificationPositiveButtonInitial: String { return L10n.tr("Localizable", "screen_session_verification_positive_button_initial") } - /// Waiting to match + /// Waiting to match… internal static var screenSessionVerificationPositiveButtonVerifyingOngoing: String { return L10n.tr("Localizable", "screen_session_verification_positive_button_verifying_ongoing") } /// Compare a unique set of emojis. internal static var screenSessionVerificationReadySubtitle: String { return L10n.tr("Localizable", "screen_session_verification_ready_subtitle") } @@ -2021,10 +2023,18 @@ internal enum L10n { internal static var screenSessionVerificationRequestAcceptedSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_request_accepted_subtitle") } /// Signed in internal static var screenSessionVerificationRequestDetailsTimestamp: String { return L10n.tr("Localizable", "screen_session_verification_request_details_timestamp") } + /// Either the request timed out, the request was denied, or there was a verification mismatch. + internal static var screenSessionVerificationRequestFailureSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_request_failure_subtitle") } + /// Verification failed + internal static var screenSessionVerificationRequestFailureTitle: String { return L10n.tr("Localizable", "screen_session_verification_request_failure_title") } /// Only continue if you initiated this verification. internal static var screenSessionVerificationRequestFooter: String { return L10n.tr("Localizable", "screen_session_verification_request_footer") } /// Verify the other device to keep your message history secure. internal static var screenSessionVerificationRequestSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_request_subtitle") } + /// Now you can read or send messages securely on your other device. + internal static var screenSessionVerificationRequestSuccessSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_request_success_subtitle") } + /// Device verified + internal static var screenSessionVerificationRequestSuccessTitle: String { return L10n.tr("Localizable", "screen_session_verification_request_success_title") } /// Verification requested internal static var screenSessionVerificationRequestTitle: String { return L10n.tr("Localizable", "screen_session_verification_request_title") } /// They don’t match diff --git a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift new file mode 100644 index 000000000..5155a6feb --- /dev/null +++ b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift @@ -0,0 +1,31 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +@MainActor +struct InvitedRoomProxyMockConfiguration { + var id = UUID().uuidString + var name: String? + var avatarURL: URL? + var members: [RoomMemberProxyMock] = .allMembers + var inviter: RoomMemberProxyMock = .mockAlice +} + +extension InvitedRoomProxyMock { + @MainActor + convenience init(_ configuration: InvitedRoomProxyMockConfiguration) { + self.init() + id = configuration.id + name = configuration.name + avatarURL = configuration.avatarURL + avatar = .room(id: configuration.id, name: configuration.name, avatarURL: configuration.avatarURL) // Note: This doesn't replicate the real proxy logic. + underlyingInviter = configuration.inviter + activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count + } +} diff --git a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift index 7e47548e0..ed88e9efe 100644 --- a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift +++ b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift @@ -71,8 +71,7 @@ extension Array where Element == RoomSummary { static let mockRooms: [Element] = [ RoomSummary(roomListItem: RoomListItemSDKMock(), id: "1", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Foundation 🔭🪐🌌", isDirect: false, avatarURL: nil, @@ -89,8 +88,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "2", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Foundation and Empire", isDirect: false, avatarURL: URL.picturesDirectory, @@ -107,8 +105,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "3", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Second Foundation", isDirect: false, avatarURL: nil, @@ -125,8 +122,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "4", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Foundation's Edge", isDirect: false, avatarURL: nil, @@ -143,8 +139,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "5", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Foundation and Earth", isDirect: true, avatarURL: nil, @@ -161,8 +156,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "6", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Prelude to Foundation", isDirect: true, avatarURL: nil, @@ -179,8 +173,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "0", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Unknown", isDirect: false, avatarURL: nil, @@ -230,8 +223,7 @@ extension Array where Element == RoomSummary { static let mockInvites: [Element] = [ RoomSummary(roomListItem: RoomListItemSDKMock(), id: "someAwesomeRoomId1", - isInvite: false, - inviter: RoomMemberProxyMock.mockCharlie, + joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), name: "First room", isDirect: false, avatarURL: URL.picturesDirectory, @@ -248,8 +240,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "someAwesomeRoomId2", - isInvite: false, - inviter: RoomMemberProxyMock.mockCharlie, + joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), name: "Second room", isDirect: true, avatarURL: nil, diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift similarity index 100% rename from ElementX/Sources/Screens/RoomScreen/View/RoomHeaderView.swift rename to ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index 96106f1ea..d253a14be 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -127,10 +127,11 @@ struct HomeScreenViewStateBindings { } struct HomeScreenRoom: Identifiable, Equatable { - enum RoomType { + enum RoomType: Equatable { case placeholder case room - case invite + case invite(inviterDetails: RoomInviterDetails?) + case knock } static let placeholderLastMessage = AttributedString("Hidden last message") @@ -143,6 +144,13 @@ struct HomeScreenRoom: Identifiable, Equatable { let type: RoomType + var inviter: RoomInviterDetails? { + if case .invite(let inviter) = type { + return inviter + } + return nil + } + let badges: Badges struct Badges: Equatable { let isDotShown: Bool @@ -164,9 +172,7 @@ struct HomeScreenRoom: Identifiable, Equatable { let lastMessage: AttributedString? let avatar: RoomAvatar - - let inviter: RoomInviterDetails? - + let canonicalAlias: String? static func placeholder() -> HomeScreenRoom { @@ -181,7 +187,6 @@ struct HomeScreenRoom: Identifiable, Equatable { timestamp: "Now", lastMessage: placeholderLastMessage, avatar: .room(id: "", name: "", avatarURL: nil), - inviter: nil, canonicalAlias: nil) } } @@ -192,17 +197,21 @@ extension HomeScreenRoom { let hasUnreadMessages = hideUnreadMessagesBadge ? false : summary.hasUnreadMessages - let isDotShown = hasUnreadMessages || summary.hasUnreadMentions || summary.hasUnreadNotifications || summary.isMarkedUnread + let isDotShown = hasUnreadMessages || summary.hasUnreadMentions || summary.hasUnreadNotifications || summary.isMarkedUnread || summary.joinRequestType?.isKnock == true let isMentionShown = summary.hasUnreadMentions && !summary.isMuted let isMuteShown = summary.isMuted let isCallShown = summary.hasOngoingCall - let isHighlighted = summary.isMarkedUnread || (!summary.isMuted && (summary.hasUnreadNotifications || summary.hasUnreadMentions)) + let isHighlighted = summary.isMarkedUnread || (!summary.isMuted && (summary.hasUnreadNotifications || summary.hasUnreadMentions)) || summary.joinRequestType?.isKnock == true - let inviter = summary.inviter.map(RoomInviterDetails.init) + let type: HomeScreenRoom.RoomType = switch summary.joinRequestType { + case .invite(let inviter): .invite(inviterDetails: inviter.map(RoomInviterDetails.init)) + case .knock: .knock + case .none: .room + } self.init(id: identifier, roomID: summary.id, - type: summary.isInvite ? .invite : .room, + type: type, badges: .init(isDotShown: isDotShown, isMentionShown: isMentionShown, isMuteShown: isMuteShown, @@ -214,7 +223,6 @@ extension HomeScreenRoom { timestamp: summary.lastMessageFormattedTimestamp, lastMessage: summary.lastMessage, avatar: summary.avatar, - inviter: inviter, canonicalAlias: summary.canonicalAlias) } } diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift index aaf7ca0fa..2abc3a770 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift @@ -69,7 +69,8 @@ struct HomeScreenInviteCell: View { @ViewBuilder private var inviterView: some View { - if let inviter = room.inviter, !room.isDirect { + if let inviter = room.inviter, + !room.isDirect { RoomInviterLabel(inviter: inviter, mediaProvider: context.mediaProvider) .font(.compound.bodyMD) .foregroundStyle(.compound.textPlaceholder) @@ -177,8 +178,7 @@ private extension HomeScreenRoom { let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - isInvite: false, - inviter: inviter, + joinRequestType: .invite(inviter: inviter), name: "Some Guy", isDirect: true, avatarURL: nil, @@ -205,8 +205,7 @@ private extension HomeScreenRoom { let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - isInvite: false, - inviter: inviter, + joinRequestType: .invite(inviter: inviter), name: "Awesome Room", isDirect: false, avatarURL: avatarURL, diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift new file mode 100644 index 000000000..a1cdf9bfb --- /dev/null +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift @@ -0,0 +1,200 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Compound +import SwiftUI + +@MainActor +struct HomeScreenKnockedCell: View { + @Environment(\.dynamicTypeSize) var dynamicTypeSize + + let room: HomeScreenRoom + let context: HomeScreenViewModel.Context + + var body: some View { + HStack(alignment: .top, spacing: 16) { + if dynamicTypeSize < .accessibility3 { + RoomAvatarImage(avatar: room.avatar, + avatarSize: .custom(52), + mediaProvider: context.mediaProvider) + .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) + .accessibilityHidden(true) + } + + mainContent + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.bottom, 16) + .padding(.trailing, 16) + .multilineTextAlignment(.leading) + .overlay(alignment: .bottom) { + separator + } + } + .padding(.top, 12) + .padding(.leading, 16) + .onTapGesture { + if let roomID = room.roomID { + context.send(viewAction: .selectRoom(roomIdentifier: roomID)) + } + } + } + + // MARK: - Private + + private var mainContent: some View { + VStack(alignment: .leading, spacing: 0) { + VStack(alignment: .leading, spacing: 0) { + HStack(alignment: .firstTextBaseline, spacing: 16) { + textualContent + badge + } + + Text(L10n.screenRoomlistKnockEventSentDescription) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPlaceholder) + .padding(.top, room.canonicalAlias == nil ? 0 : 4) + .padding(.trailing, 16) + } + .fixedSize(horizontal: false, vertical: true) + .accessibilityElement(children: .combine) + } + } + + @ViewBuilder + private var textualContent: some View { + VStack(alignment: .leading, spacing: 0) { + Text(title) + .font(.compound.bodyLGSemibold) + .foregroundColor(.compound.textPrimary) + .lineLimit(2) + + if let subtitle { + Text(subtitle) + .font(.compound.bodyMD) + .foregroundColor(.compound.textPlaceholder) + } + } + .frame(maxWidth: .infinity, alignment: .leading) + } + + private var separator: some View { + Rectangle() + .fill(Color.compound.borderDisabled) + .frame(height: 1 / UIScreen.main.scale) + } + + private var title: String { + room.name + } + + private var subtitle: String? { + room.canonicalAlias + } + + private var badge: some View { + Circle() + .scaledFrame(size: 12) + .foregroundColor(.compound.iconAccentTertiary) + } +} + +struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + ScrollView { + VStack(spacing: 0) { + HomeScreenKnockedCell(room: .dmInvite, + context: viewModel().context) + + HomeScreenKnockedCell(room: .dmInvite, + context: viewModel().context) + + HomeScreenKnockedCell(room: .roomKnocked(), + context: viewModel().context) + + HomeScreenKnockedCell(room: .roomKnocked(), + context: viewModel().context) + + HomeScreenKnockedCell(room: .roomKnocked(alias: "#footest:somewhere.org", avatarURL: .picturesDirectory), + context: viewModel().context) + + HomeScreenKnockedCell(room: .roomKnocked(alias: "#footest:somewhere.org"), + context: viewModel().context) + .dynamicTypeSize(.accessibility1) + .previewDisplayName("Aliased room (AX1)") + } + } + } + + static func viewModel() -> HomeScreenViewModel { + let clientProxy = ClientProxyMock(.init()) + + let userSession = UserSessionMock(.init(clientProxy: clientProxy)) + + return HomeScreenViewModel(userSession: userSession, + analyticsService: ServiceLocator.shared.analytics, + appSettings: ServiceLocator.shared.settings, + selectedRoomPublisher: CurrentValueSubject(nil).asCurrentValuePublisher(), + userIndicatorController: ServiceLocator.shared.userIndicatorController) + } +} + +@MainActor +private extension HomeScreenRoom { + static var dmInvite: HomeScreenRoom { + let inviter = RoomMemberProxyMock() + inviter.displayName = "Jack" + inviter.userID = "@jack:somewhere.com" + + let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), + id: "@someone:somewhere.com", + joinRequestType: .invite(inviter: inviter), + name: "Some Guy", + isDirect: true, + avatarURL: nil, + heroes: [.init(userID: "@someone:somewhere.com")], + lastMessage: nil, + lastMessageFormattedTimestamp: nil, + unreadMessagesCount: 0, + unreadMentionsCount: 0, + unreadNotificationsCount: 0, + notificationMode: nil, + canonicalAlias: "#footest:somewhere.org", + hasOngoingCall: false, + isMarkedUnread: false, + isFavourite: false) + + return .init(summary: summary, hideUnreadMessagesBadge: false) + } + + static func roomKnocked(alias: String? = nil, avatarURL: URL? = nil) -> HomeScreenRoom { + let inviter = RoomMemberProxyMock() + inviter.displayName = "Luca" + inviter.userID = "@jack:somewhi.nl" + inviter.avatarURL = avatarURL + + let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), + id: "@someone:somewhere.com", + joinRequestType: .invite(inviter: inviter), + name: "Awesome Room", + isDirect: false, + avatarURL: avatarURL, + heroes: [.init(userID: "@someone:somewhere.com")], + lastMessage: nil, + lastMessageFormattedTimestamp: nil, + unreadMessagesCount: 0, + unreadMentionsCount: 0, + unreadNotificationsCount: 0, + notificationMode: nil, + canonicalAlias: alias, + hasOngoingCall: false, + isMarkedUnread: false, + isFavourite: false) + + return .init(summary: summary, hideUnreadMessagesBadge: false) + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomList.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomList.swift index 393b5c722..fb224413a 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomList.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomList.swift @@ -32,6 +32,8 @@ struct HomeScreenRoomList: View { .redacted(reason: .placeholder) case .invite: HomeScreenInviteCell(room: room, context: context) + case .knock: + HomeScreenKnockedCell(room: room, context: context) case .room: let isSelected = context.viewState.selectedRoomID == room.id diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift index fbe2e23c0..d259e53e1 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenCoordinator.swift @@ -49,7 +49,7 @@ final class JoinRoomScreenCoordinator: CoordinatorProtocol { switch action { case .joined: actionsSubject.send(.joined) - case .cancelled: + case .dismiss: actionsSubject.send(.cancelled) } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift index a0bf1d91c..5def71272 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift @@ -9,7 +9,7 @@ import Foundation enum JoinRoomScreenViewModelAction { case joined - case cancelled + case dismiss } enum JoinRoomScreenInteractionMode { @@ -65,6 +65,7 @@ struct JoinRoomScreenViewStateBindings { enum JoinRoomScreenAlertType { case declineInvite + case cancelKnock } enum JoinRoomScreenViewAction { diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 74e7a6966..b97b85bd7 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -59,8 +59,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo case .declineInvite: showDeclineInviteConfirmationAlert() case .cancelKnock: - // TODO: implement once available - break + showCancelKnockConfirmationAlert() } } @@ -78,15 +77,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo Task { await updateRoomDetails() } } - // Using only the preview API isn't enough as it's not capable - // of giving us information for non-joined rooms (at least not on synapse) - // See if we known about the room locally and, if so, have that - // take priority over the preview one. - - if let room = await clientProxy.roomForIdentifier(roomID) { - self.room = room - await updateRoomDetails() - } + await updateRoom() switch await clientProxy.roomPreviewForIdentifier(roomID, via: via) { case .success(let roomPreviewDetails): @@ -99,6 +90,17 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo } } + private func updateRoom() async { + // Using only the preview API isn't enough as it's not capable + // of giving us information for non-joined rooms (at least not on synapse) + // See if we known about the room locally and, if so, have that + // take priority over the preview one. + if let room = await clientProxy.roomForIdentifier(roomID) { + self.room = room + await updateRoomDetails() + } + } + private func updateRoomDetails() async { var roomProxy: RoomProxyProtocol? var inviter: RoomInviterDetails? @@ -188,7 +190,8 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo switch await clientProxy.knockRoomAlias(alias, message: state.bindings.knockMessage.isBlank ? nil : state.bindings.knockMessage) { case .success: - state.mode = .knocked + // The room should become knocked through the sync + await updateRoom() case .failure(let error): MXLog.error("Failed knocking room alias: \(alias) with error: \(error)") userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) @@ -198,7 +201,8 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo via: via, message: state.bindings.knockMessage.isBlank ? nil : state.bindings.knockMessage) { case .success: - state.mode = .knocked + // The room should become knocked through the sync + await updateRoom() case .failure(let error): MXLog.error("Failed knocking room id: \(roomID) with error: \(error)") userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) @@ -220,6 +224,14 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo secondaryButton: .init(title: L10n.actionDecline, role: .destructive, action: { Task { await self.declineInvite() } })) } + private func showCancelKnockConfirmationAlert() { + state.bindings.alertInfo = .init(id: .cancelKnock, + title: L10n.screenJoinRoomCancelKnockAlertTitle, + message: L10n.screenJoinRoomCancelKnockAlertDescription, + primaryButton: .init(title: L10n.actionNo, role: .cancel, action: nil), + secondaryButton: .init(title: L10n.screenJoinRoomCancelKnockAlertConfirmation, role: .destructive, action: { Task { await self.cancelKnock() } })) + } + private func declineInvite() async { defer { userIndicatorController.retractIndicatorWithId(roomID) @@ -236,6 +248,29 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo if case .failure = result { userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) + } else { + actionsSubject.send(.dismiss) + } + } + + private func cancelKnock() async { + defer { + userIndicatorController.retractIndicatorWithId(roomID) + } + + userIndicatorController.submitIndicator(UserIndicator(id: roomID, type: .modal, title: L10n.commonLoading, persistent: true)) + + guard case let .knocked(roomProxy) = room else { + userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) + return + } + + let result = await roomProxy.cancelKnock() + + if case .failure = result { + userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown)) + } else { + actionsSubject.send(.dismiss) } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index 419e46329..f47e63c63 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -14,7 +14,7 @@ struct JoinRoomScreen: View { @ObservedObject var context: JoinRoomScreenViewModel.Context var body: some View { - FullscreenDialog(topPadding: 80, background: .bloom) { + FullscreenDialog(topPadding: context.viewState.mode == .knocked ? 151 : 35, background: .bloom) { if context.viewState.mode == .loading { EmptyView() } else { @@ -27,13 +27,15 @@ struct JoinRoomScreen: View { .background() .backgroundStyle(.compound.bgCanvasDefault) .navigationBarTitleDisplayMode(.inline) + .toolbar { toolbar } } @ViewBuilder var mainContent: some View { - if context.viewState.mode == .knocked { + switch context.viewState.mode { + case .knocked: knockedView - } else { + default: defaultView } } @@ -54,7 +56,7 @@ struct JoinRoomScreen: View { if let subtitle = context.viewState.subtitle { Text(subtitle) - .font(.compound.bodyMD) + .font(.compound.bodyLG) .foregroundStyle(.compound.textSecondary) .multilineTextAlignment(.center) } @@ -101,7 +103,7 @@ struct JoinRoomScreen: View { } } } - + @ViewBuilder private var knockMessage: some View { VStack(alignment: .leading, spacing: 12) { @@ -158,6 +160,17 @@ struct JoinRoomScreen: View { Button(L10n.actionAccept) { context.send(viewAction: .acceptInvite) } .buttonStyle(.compound(.primary)) } + + @ToolbarContentBuilder + private var toolbar: some ToolbarContent { + if context.viewState.mode == .knocked { + ToolbarItem(placement: .principal) { + RoomHeaderView(roomName: context.viewState.title, + roomAvatar: context.viewState.avatar, + mediaProvider: context.mediaProvider) + } + } + } } // MARK: - Previews @@ -221,10 +234,17 @@ struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { if mode == .unknown { clientProxy.roomPreviewForIdentifierViaReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) } else { - if mode == .knocked { + switch mode { + case .knocked: clientProxy.roomForIdentifierClosure = { _ in - .knocked(KnockedRoomProxyMock(.init())) + .knocked(KnockedRoomProxyMock(.init(avatarURL: URL.homeDirectory))) } + case .invited: + clientProxy.roomForIdentifierClosure = { _ in + .invited(InvitedRoomProxyMock(.init(avatarURL: URL.homeDirectory))) + } + default: + break } clientProxy.roomPreviewForIdentifierViaReturnValue = .success(.init(roomID: "1", name: "The Three-Body Problem - 三体", diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 643b8844e..0bba67ad5 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -417,7 +417,7 @@ class ClientProxy: ClientProxyProtocol { func knockRoom(_ roomID: String, via: [String], message: String?) async -> Result { do { - let _ = try await client.knock(roomIdOrAlias: roomID, reason: nil, serverNames: via) + let _ = try await client.knock(roomIdOrAlias: roomID, reason: message, serverNames: via) await waitForRoomToSync(roomID: roomID, timeout: .seconds(30)) return .success(()) } catch { @@ -428,7 +428,7 @@ class ClientProxy: ClientProxyProtocol { func knockRoomAlias(_ roomAlias: String, message: String?) async -> Result { do { - let room = try await client.knock(roomIdOrAlias: roomAlias, reason: nil, serverNames: []) + let room = try await client.knock(roomIdOrAlias: roomAlias, reason: message, serverNames: []) await waitForRoomToSync(roomID: room.id(), timeout: .seconds(30)) return .success(()) } catch { diff --git a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift index 942baa041..7ca349f33 100644 --- a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift @@ -76,7 +76,11 @@ class KnockedRoomProxy: KnockedRoomProxyProtocol { } func cancelKnock() async -> Result { - // TODO: Implement this once the API is available - .failure(.invalidURL) + do { + return try await .success(room.leave()) + } catch { + MXLog.error("Failed cancelling the knock with error: \(error)") + return .failure(.sdkError(error)) + } } } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift index 942a78704..429cba58a 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift @@ -9,12 +9,32 @@ import Foundation import MatrixRustSDK struct RoomSummary { + enum JoinRequestType { + case invite(inviter: RoomMemberProxyProtocol?) + case knock + + var isInvite: Bool { + if case .invite = self { + return true + } else { + return false + } + } + + var isKnock: Bool { + if case .knock = self { + return true + } else { + return false + } + } + } + let roomListItem: RoomListItem let id: String - let isInvite: Bool - let inviter: RoomMemberProxyProtocol? + let joinRequestType: JoinRequestType? let name: String let isDirect: Bool @@ -67,10 +87,9 @@ extension RoomSummary { unreadNotificationsCount = hasUnreadNotifications ? 1 : 0 notificationMode = settingsMode canonicalAlias = nil - inviter = nil hasOngoingCall = false - isInvite = false + joinRequestType = nil isMarkedUnread = false isFavourite = false } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index db51b77c8..4622c5661 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -255,10 +255,15 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { let notificationMode = roomInfo.cachedUserDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) } + let joinRequestType: RoomSummary.JoinRequestType? = switch roomInfo.membership { + case .invited: .invite(inviter: inviterProxy) + case .knocked: .knock + default: nil + } + return RoomSummary(roomListItem: roomListItem, id: roomInfo.id, - isInvite: roomInfo.membership == .invited, - inviter: inviterProxy, + joinRequestType: joinRequestType, name: roomInfo.displayName ?? roomInfo.id, isDirect: roomInfo.isDirect, avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)), diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index 930131413..e1c8b5f6f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -18,7 +18,6 @@ enum TimelineKind { enum TimelineProxyError: Error { case sdkError(Error) - case failedEditing case failedRedacting case failedPaginatingEndReached } diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index 84726015b..c68538da0 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -245,6 +245,12 @@ extension PreviewTests { } } + func test_homeScreenKnockedCell() { + for preview in HomeScreenKnockedCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_homeScreenRecoveryKeyConfirmationBanner() { for preview in HomeScreenRecoveryKeyConfirmationBanner_Previews._allPreviews { assertSnapshots(matching: preview) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png new file mode 100644 index 000000000..874d53630 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37d4585f90bb64bf739101413ed1a7e24db10161670bd0ba38409e146b31645f +size 175190 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png new file mode 100644 index 000000000..750e5a441 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:216f3373784519707d3659d6282a1c59202f189407c2f1226bdff510a5f9261c +size 188573 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png new file mode 100644 index 000000000..b819d05cd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c674069ca803e934769bb070a528e415ca12de00f722fbb67bf0624a1f24305f +size 120759 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png new file mode 100644 index 000000000..adc229bec --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d39cc8560c7f57e27764b782dd5ef07e31d883d265f675d8e4f394dccd82e69 +size 142235 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 index c20572b22..f190faed8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:227bd893c17ef8a6042e6eab9372eb78c3cbb631c4b232f13d6e6f0179ce02c7 -size 1982377 +oid sha256:d5b3a8bd64746aad774b15fc3e3500bbab4144d64ed4f8714f9b2527c70a494c +size 1990774 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png index 7fc18921f..a140b1c4b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:146c20f80acac9bf9497aa93562cb930bea02e6fb82507d971a22c26bf3e28a6 -size 1946311 +oid sha256:b6be25a2a046c3d1088ae6f87e4e1e0033062225c624095d679f1083ffe538b6 +size 1945746 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png index 3b61214cd..80328b815 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:adb3e3a08681e2febea9cd377862eededc6b576bfe06c753bf075eb886f55f9f -size 1788568 +oid sha256:46447c25230d95f04d122924d938f6f4b5eacd633140e586c3c276322f8e8b75 +size 1791354 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png index 36123d267..be7b7aed9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47bda34db0009a5f2d04a9ab3fdb761d9efb266046c85abf786051ec3d30f081 -size 1973723 +oid sha256:e0070dcdfe989211600c14fdb7b96af79cfb2b50ae8c3d560f7fe738b368be48 +size 1982637 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 f57487803..0b5feb40a 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:efda9145642c0bef47507f9de249565cb09897bfed8f4fa6ae79ec792c067fb5 -size 1890674 +oid sha256:c85ef3dcec00111c6c6bb9fe6cfbb1f2bbf332631cc681ea41642f411a4c761e +size 1890475 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png index 5bc940cd7..369116162 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91e9b65c2ad0972f12351bad8d93c627a9d73a87cb22356cd9fc53c81625ed7d -size 1983445 +oid sha256:41f91af2b20ff571cdf281d4dedaf1f6749a8fdaf33508a1b70511ef6e477af4 +size 1995837 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png index d9ded5d4e..daf998078 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48852e2e65d9c3000b2069521628f577426801ab4a804a1f30100540a573bc66 -size 1947292 +oid sha256:daf1b08dbe20c63aa66d1c16e3bc41fdc92a54ad4f143ccfcd9ca8382964a0fe +size 1946727 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png index d34ffa65c..e0acdc11e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:338b8be69ace718a2796101e2ccfbe93dca412e299279a6078b785fec10e7e4b -size 1797161 +oid sha256:08e0296e33a657e0c42f95cb2e4963cb8f32c3a37979262cd76bc4c3ac3a7132 +size 1799819 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png index c32281cae..1a6c7a770 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d768cff2a5e42c223808f4fc3b1b3f7fbfe13d94711ae2ddeb77d24c2088517 -size 1990759 +oid sha256:8283d5d60db3b91caa096216e4dbb1d5e5342375080c81e5814acbb01b41c8c9 +size 2000079 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 9b611d6ef..e3b1a370d 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:b1e33030ab7373ae71f3ac6b2580a1187f8ec21d81da94831a3f8ea6fdbcfc0a -size 1895360 +oid sha256:0fde3ae365ead45c6789493ec6dcd5569f420d823d778ebe2549b36e1076052a +size 1895270 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 index c97135818..30981c1a0 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5bb2adb3c27c6adad8d72174d662688ce1b40a90d748b00354717abf5d37f56 -size 817765 +oid sha256:616a8a5fe92ef87797d9a69bd5d7581e685edad21b002bf079d1a02fdb782987 +size 827638 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.Join.png index c1384ca8d..4e9483a8d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eca394ab7064165321d8eba0c1110b56c5e815260cef52f69cc61ec7c4bc7d3b -size 796819 +oid sha256:6d7390ef83a9fb7e8887aff95c03282d4fbcf3826cf3e254d523373a2c434df0 +size 798961 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.Knock.png index f0f6bd47a..ce2bdf2f6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0be47f8b5c89c0d03e4713e32686c457452851ccc246bf4588f5cb5f82fdbabc -size 701611 +oid sha256:3f9518a386e4c12c9e1527eb5f841fb0ca56fc8658529b58d6d459376caca39b +size 705027 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png index 7f840a171..8db4a9796 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f21b9720b09a4fdc89f4f1f25548200d159b404ed6431693defe99c401f99d2 -size 812339 +oid sha256:19d3b48e373ed4e263c9cb0f6e5a3566a9c6612f19da8468be420eca0a10cd92 +size 819795 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 90e6e1089..c9a6df3a9 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:c001018d811bda7d9db87503f38d94dc23a2102bc134d08b69e3af171ecbf350 -size 755374 +oid sha256:068da1ad317aefc4ebed25f4ac259cd5fe46a5ce444b6e22051455d69bfea78e +size 756893 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 index c70e647cc..1de1b350e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a922e59c0fec9924f16c3e224af836de79d818fab3e686c1fb34c707be1fc23 -size 820225 +oid sha256:6ecca9bbfa7a1d245a96fc27aacfb5d60931ba1437639ebd8e9ff1756bd705c6 +size 835366 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png index 0acd1dcc6..42fb8407b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fb7955f605d2ad9e5678438af15a1a354baab5f00e59ca0ff458759e93d76b1 -size 798533 +oid sha256:450d28a2af4b81f2db2e8a1fb28405d029439cabf5f48688b448391dd7e43b05 +size 800675 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png index 999c04fe9..dfd17d625 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:471ae5bf707a3f9e91b7f8cea098287bb21d618297d027a72c105575b5049ff8 -size 709284 +oid sha256:858759589a323ce04e894f398c230c0454f64a3c3148b183f9ecdbeb29955b89 +size 714177 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png index 81a9e865f..8407998f1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ae617786ed8ee75c55bf33222bdf80faca1dac30a5d0fca84175e3ed7f42d9f -size 829745 +oid sha256:eb3a1c2ac88a74a4f9c402a46a8512abc2596937b92c3d17fa30a7cdf10ce22a +size 835796 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 e943319e8..31f5cf6eb 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:93d65076d29abb7a6476b649fae781a8be6bad9d4b905c8251b7253498af3d3e -size 761944 +oid sha256:eaa7027ce0d6ba02e75bc6b35cd7080a4cf217e6d36b3aa2bcebfce6355ad117 +size 763528 diff --git a/UnitTests/Sources/HomeScreenRoomTests.swift b/UnitTests/Sources/HomeScreenRoomTests.swift index bb47ffc0c..1cbe828d2 100644 --- a/UnitTests/Sources/HomeScreenRoomTests.swift +++ b/UnitTests/Sources/HomeScreenRoomTests.swift @@ -23,8 +23,7 @@ class HomeScreenRoomTests: XCTestCase { hasOngoingCall: Bool) { roomSummary = RoomSummary(roomListItem: .init(noPointer: .init()), id: "Test room", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: "Test room", isDirect: false, avatarURL: nil, diff --git a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift index 42b1b6a52..2f8b6e052 100644 --- a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift +++ b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift @@ -56,6 +56,23 @@ class JoinRoomScreenViewModelTests: XCTestCase { }.fulfill() } + func testCancelKnock() async throws { + setupViewModel(knocked: true) + + try await deferFulfillment(viewModel.context.$viewState) { state in + state.mode == .knocked + }.fulfill() + + context.send(viewAction: .cancelKnock) + XCTAssertEqual(viewModel.context.alertInfo?.id, .cancelKnock) + + let deferred = deferFulfillment(viewModel.actionsPublisher) { action in + action == .dismiss + } + context.alertInfo?.secondaryButton?.action?() + try await deferred.fulfill() + } + private func setupViewModel(throwing: Bool = false, knocked: Bool = false) { let clientProxy = ClientProxyMock(.init()) @@ -75,7 +92,10 @@ class JoinRoomScreenViewModelTests: XCTestCase { if knocked { clientProxy.roomForIdentifierClosure = { _ in - .knocked(KnockedRoomProxyMock(.init())) + let roomProxy = KnockedRoomProxyMock(.init()) + // to test the cancel knock function + roomProxy.cancelKnockUnderlyingReturnValue = .success(()) + return .knocked(roomProxy) } } diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 20205e520..3ab0e77fd 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -80,8 +80,7 @@ class LoggingTests: XCTestCase { let heroName = "Pseudonym" let roomSummary = RoomSummary(roomListItem: .init(noPointer: .init()), id: "myroomid", - isInvite: false, - inviter: nil, + joinRequestType: nil, name: roomName, isDirect: true, avatarURL: nil, diff --git a/UnitTests/Sources/RoomSummaryTests.swift b/UnitTests/Sources/RoomSummaryTests.swift index 55cb93948..2626351eb 100644 --- a/UnitTests/Sources/RoomSummaryTests.swift +++ b/UnitTests/Sources/RoomSummaryTests.swift @@ -56,8 +56,7 @@ class RoomSummaryTests: XCTestCase { func makeSummary(isDirect: Bool, hasRoomAvatar: Bool) -> RoomSummary { RoomSummary(roomListItem: .init(noPointer: .init()), id: roomDetails.id, - isInvite: false, - inviter: nil, + joinRequestType: nil, name: roomDetails.name, isDirect: isDirect, avatarURL: hasRoomAvatar ? roomDetails.avatarURL : nil,