fix: blocked user - WPB-24403#4958
Conversation
…rry-pick # Conflicts: # wire-ios/WireUITests/ConversationTests.swift
|
There was a problem hiding this comment.
Pull request overview
Fixes an issue where blocking a user could cause the 1:1 conversation (and/or its MLS variant) to disappear or become unusable, by preventing participant/link teardown on partial backend payloads and by avoiding local deletion of 1:1 conversations on backend 404s. It also adds UI affordances for block/unblock in the conversation list context menu, and introduces an app-version migration to restore previously hidden blocked 1:1 conversations.
Changes:
- Preserve 1:1 conversations when backend responses omit the other participant (blocked-side behavior) and avoid overwriting established MLS 1:1 links with the Proteus connection conversation.
- Avoid deleting 1:1 conversations locally when
GET /conversations/{id}returns 404; only delete locally for groups. - Add UI + locators + UI tests and snapshots for block/unblock flows, including a “You blocked this user” bottom bar replacing the input bar.
Reviewed changes
Copilot reviewed 61 out of 63 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| WireUI/Sources/WireLocators/Locators.swift | Adds separate locators for block vs unblock context-menu actions. |
| WireDomain/Tests/WireDomainTests/WorkAgent/WorkItem/UpdateConversationItemTests.swift | Adds test coverage for “don’t delete 1:1 on not found”. |
| WireDomain/Tests/WireDomainTests/LocalStores/ConversationLocalStoreTests.swift | Tests preserving MLS 1:1 usability when members list is empty but linked user exists. |
| WireDomain/Tests/WireDomainTests/LocalStores/ConnectionsLocalStoreTests.swift | Tests that storing a connection preserves an established MLS 1:1 link. |
| WireDomain/Sources/WireDomainSupport/Sourcery/generated/AutoMockable.generated.swift | Updates mock to include new isGroupConversation repository API. |
| WireDomain/Sources/WireDomain/WorkAgent/WorkItem/UpdateConversationItem.swift | Deletes missing conversations locally only if they’re groups. |
| WireDomain/Sources/WireDomain/Repositories/Conversations/Repository/ConversationRepository.swift | Implements isGroupConversation(id:domain:). |
| WireDomain/Sources/WireDomain/Repositories/Conversations/Protocols/ConversationRepositoryProtocol.swift | Adds isGroupConversation to repository contract. |
| WireDomain/Sources/WireDomain/Repositories/Conversations/LocalStore/ConversationLocalStore+Group.swift | Prevents tearing down established 1:1 when other member is missing but link exists. |
| WireDomain/Sources/WireDomain/Repositories/Conversations/LocalStore/ConversationLocalStore.swift | Prevents participant removal for 1:1 updates from /conversations/list. |
| WireDomain/Sources/WireDomain/Repositories/Connections/ConnectionsLocalStore.swift | Preserves established MLS one-on-one link when processing Proteus connection conversation. |
| wire-ios/WireUITests/Pages/ConversationsPage.swift | Adds unblock locator usage and unblock helper method. |
| wire-ios/WireUITests/ConversationTests.swift | Adds UI test for block/unblock and verifying the conversation remains visible. |
| wire-ios/Wire-iOS/Sources/UserInterface/GroupDetails/ConversationActions/ConversationActionController+Block.swift | Routes block vs unblock to different connected-user operations. |
| wire-ios/Wire-iOS/Sources/UserInterface/GroupDetails/ConversationActions/ConversationAction.swift | Assigns accessibility identifiers for block/unblock context-menu actions. |
| wire-ios/Wire-iOS/Sources/UserInterface/ConversationList/ListContent/ConversationListContentController/ConversationListContentController.swift | Sets identifiers on context-menu UIActions for UI testing. |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/UseCases/GetParticipantImageSourceUseCase.swift | Shows a composed “blocked” avatar image for blocked users in account-image UI. |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/InputBar/ConversationInputBarViewController/ConversationInputBarViewController.swift | Adds support for hiding the input bar when self blocked the other user. |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/ConversationViewController+Constraints.swift | Adds/removes a blocked-user bottom bar and adjusts constraints accordingly. |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/ConversationViewController.swift | Collapses input bar and toggles blocked-user bar based on blocked state. |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/Content/Cells/ConfigurationMessageCell/Components/ConversationSenderMessageDetailsCell.swift | Uses BadgeUserImageView to show blocked badge (without desaturation). |
| wire-ios/Wire-iOS/Sources/UserInterface/Conversation/BlockedUserBottomBarViewController.swift | Introduces “You blocked this user” bottom bar UI. |
| wire-ios/Wire-iOS/Sources/UserInterface/ConnectRequests/OneOnOneConversationHeaderView.swift | Uses BadgeUserImageView to show blocked badge (without desaturation). |
| wire-ios/Wire-iOS/Resources/Localization/ar.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/Base.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/da.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/de.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/es.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/et.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/fi.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/fr.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/it.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/ja.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/lt.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/nl.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/pl.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/pt-BR.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/ru.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/sl.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/tr.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/uk.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/zh-Hans.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Resources/Localization/zh-Hant.lproj/Localizable.strings | Adds conversation.input_bar.blocked_user string. |
| wire-ios/Wire-iOS/Generated/Strings+Generated.swift | Adds generated accessor for conversation.input_bar.blocked_user. |
| wire-ios/Wire-iOS Tests/ReferenceImages/OneOnOneConversationHeaderViewSnapshotTests/testWithUserName.1.png | Updates snapshot reference image (Git LFS pointer). |
| wire-ios/Wire-iOS Tests/ReferenceImages/OneOnOneConversationHeaderViewSnapshotTests/testWithUserName_Federated.1.png | Updates snapshot reference image (Git LFS pointer). |
| wire-ios/Wire-iOS Tests/ReferenceImages/OneOnOneConversationHeaderViewSnapshotTests/testWithoutUserName.1.png | Updates snapshot reference image (Git LFS pointer). |
| wire-ios/Wire-iOS Tests/ReferenceImages/OneOnOneConversationHeaderViewSnapshotTests/testBlockedUser.1.png | Adds snapshot reference image for blocked user header (Git LFS pointer). |
| wire-ios/Wire-iOS Tests/ReferenceImages/ConversationViewControllerSnapshotTests/testThatBlockedUserBarReplacesInputBar_WhenSelfBlockedTheOtherUser.1.png | Adds snapshot reference image for blocked-user bar (Git LFS pointer). |
| wire-ios/Wire-iOS Tests/OneOnOneConversationHeaderViewSnapshotTests.swift | Extends header snapshots to cover blocked state. |
| wire-ios/Wire-iOS Tests/ConversationViewControllerSnapshotTests.swift | Adds snapshot coverage for blocked-user bar and injects a mock image source use case. |
| wire-ios-sync-engine/Tests/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_22_0Tests.swift | Tests restoring hidden blocked 1:1 conversations via migration. |
| wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift | Registers new AppVersionMigration_4_22_0. |
| wire-ios-sync-engine/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_22_0.swift | Adds migration restoring blocked 1:1 conversations incorrectly marked deleted remotely. |
| wire-ios-sync-engine/Source/Synchronization/ZMSyncStrategy.m | Fixes a teardown race by capturing strong refs before enqueuing a block. |
| wire-ios-request-strategy/Tests/Sources/Payloads/Processing/ConversationEventPayloadProcessorTests.swift | Adds regression test for preserving established MLS 1:1 when other member missing. |
| wire-ios-request-strategy/Tests/Sources/Payloads/Processing/ConnectionPayloadProcessorTests.swift | Adds regression tests for not overwriting established MLS 1:1 link. |
| wire-ios-request-strategy/Sources/Payloads/Processing/ConversationEventPayloadProcessor.swift | Preserves established 1:1 when other member missing; prevents participant removal from partial list payloads. |
| wire-ios-request-strategy/Sources/Payloads/Processing/ConnectionPayloadProcessor.swift | Preserves established MLS 1:1 link when processing Proteus connection conversation. |
| wire-ios-data-model/Tests/Model/Observer/ConversationListObserverTests.swift | Updates expectations so blocked 1:1 remains in the list. |
| wire-ios-data-model/Tests/Model/ConversationList/ZMConversationListTests.m | Updates list filtering expectations to include blocked 1:1 conversations. |
| wire-ios-data-model/Source/Model/Conversation/ConversationPredicateFactory.swift | Includes blocked connections in 1:1 list predicates (accepted-or-blocked). |
| wire-ios-data-model/Source/MLS/OneOnOne/OneOnOneSource.swift | Carries over the most recent proteus lastModifiedDate to keep MLS row position stable. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Test Results – batch 22 102 tests 2 102 ✅ 2m 1s ⏱️ Results for commit fa3ae5b. ♻️ This comment has been updated with latest results. |
Test Results – batch 0 2 files 183 suites 1m 19s ⏱️ Results for commit fa3ae5b. ♻️ This comment has been updated with latest results. |
Test Results – batch 1 2 files 551 suites 5m 57s ⏱️ For more details on these failures, see this check. Results for commit fa3ae5b. ♻️ This comment has been updated with latest results. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>



Issue
When blocking user, the user is not displayed in the conversation list.
This restores previously fixes.
When sending a message, we sync the conversation for mls, the backend returns the conversation without the blocked user, we update the conversation participants and when we render the conversation icon for 1:1 we miss the other participant.
Solution: don't remove participants for 1:1 conversation 27d2c58
Note: this needs to be merged once 4.24.0 is bumped
Testing
Checklist
[WPB-XXX].UI accessibility checklist
If your PR includes UI changes, please utilize this checklist: