Skip to content

Show deleted messages in channel preview + missing channel item redesign#1338

Open
nuno-vieira wants to merge 17 commits intodevelopfrom
fix/deleted-messages-in-channel-list
Open

Show deleted messages in channel preview + missing channel item redesign#1338
nuno-vieira wants to merge 17 commits intodevelopfrom
fix/deleted-messages-in-channel-list

Conversation

@nuno-vieira
Copy link
Copy Markdown
Member

@nuno-vieira nuno-vieira commented Mar 27, 2026

πŸ”— Issue Links

IOS-1506

Depends on: GetStream/stream-chat-swift#4024

🎯 Goal

Deleted messages should be visible in the channel list preview.

πŸ“ Summary

  • Compute the channel preview message in the UI layer from channel.latestMessages, filtering only ephemeral messages
  • Show deleted messages in the channel preview with nosign icon and "Message deleted" text
  • Remove InjectedChannelInfo and simplify ChatChannelListItem with inline private computed properties
  • Remove @MainActor extensions on ChatChannel β€” formatting logic now lives in the view
  • Update "No messages" to "No messages yet" per Figma
  • Add snapshot tests for deleted, pending, ephemeral-skipped, and empty message previews
  • Add unit tests for MessagePreviewFormatter handling of deleted messages

πŸ›  Implementation

The ChatChannel.previewMessage property was removed from the core SDK (see linked PR). The preview message is now computed in the SwiftUI view layer as channel.latestMessages.first(where: { $0.type != .ephemeral }), which allows deleted messages to appear in the preview while still filtering out ephemeral (Giphy) messages.

InjectedChannelInfo was removed as it was unnecessary indirection β€” its only real purpose was suppressing unread badges for the selected channel, which is now handled by a simple isSelected: Bool property.

πŸ§ͺ Manual Testing Notes

  • Open a channel and send a few messages, then delete the latest β€” verify the preview shows "Message deleted" with nosign icon
  • For deleted messages you sent, verify "You:" prefix appears with no read indicators
  • Send a message in a poor connection scenario β€” verify the clock icon appears for pending state

β˜‘οΈ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

Summary by CodeRabbit

  • New Features

    • Channel list now shows a β€œdeleted message” placeholder in previews for deleted messages.
  • Updates

    • Message previews skip ephemeral messages to show the previous visible message.
    • Unread badge visibility now respects channel selection state.
    • Empty channel text updated to "No messages yet."

@nuno-vieira nuno-vieira requested a review from a team as a code owner March 27, 2026 15:37
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Important

Review skipped

Review was skipped due to path filters

β›” Files ignored due to path filters (6)
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_channelListView_channelAvatarUpdated.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_channelListView_themedNavigationBar.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_chatChannelListViewSansNavigation_snapshot.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_chatChannelListView_showChannelListDividerOnLastItem_snapshot.disabled.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_chatChannelListView_showChannelListDividerOnLastItem_snapshot.enabled.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListView_Tests/test_chatChannelListView_snapshot.1.png is excluded by !**/*.png

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4685e8a4-1f8c-4129-9b44-c923d6dc254f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • πŸ” Trigger review
πŸ“ Walkthrough

Walkthrough

Channel list UI removed the injected InjectedChannelInfo path and now uses an isSelected: Bool flag; preview/timestamp/subtitle/draft/read logic is computed locally. Deleted-message previews are shown; tests, Core Data model, formatter, and package reference adjusted.

Changes

Cohort / File(s) Summary
Channel list UI & demo
Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListItem.swift, Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelNavigatableListItem.swift, DemoAppSwiftUI/PinChannelHelpers.swift
Removed InjectedChannelInfo usage; ChatChannelListItem now takes isSelected: Bool and computes preview/timestamp/subtitle/draft/read state locally. Navigatable list item passes selection flag rather than injected info.
View model
Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift
Removed updateSelectedChannelData() and simplified handleChannelAppearance() to always call updateChannels() when updates were skipped; search mapping now uses latestMessages.first for selection info.
Message preview formatting
Sources/StreamChatSwiftUI/Utils/MessagePreviewFormatter.swift
Short-circuits on deleted messages: format(_:in:) and formatContent(for:in:) return the deleted-message placeholder for isDeleted messages.
Core Data model
StreamChatSwiftUITests/Infrastructure/Shared/StreamChatModel.xcdatamodeld/.../contents
Removed ChannelDTO.previewMessage and MessageDTO.previewOfChannel relationship entries from the model file.
Localization & project config
Sources/StreamChatSwiftUI/Resources/en.lproj/Localizable.strings, StreamChatSwiftUI.xcodeproj/project.pbxproj
Updated empty-state text to "No messages yet"; updated remote Swift Package reference branch for stream-chat-swift.
Tests
StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListItemView_Tests.swift, StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListViewModel_Tests.swift, StreamChatSwiftUITests/Tests/Utils/MessagePreviewFormatter_Tests.swift, StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerViewModel_Tests.swift
Removed reliance on previewMessage in mocks; added/updated snapshot and unit tests for deleted messages, pending/empty states, and adjusted assertions that referenced injected channel info.
Changelog
CHANGELOG.md
Added entries noting deleted-message preview and removal of InjectedChannelInfo from channel list item.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through previews, found what's gone,
Replaced the injected thread with a simple baton,
Flags for selection, neat and clear,
Deleted lines hush what we used to hear,
A tiny rabbit cheersβ€”changes are near! πŸ₯•

πŸš₯ Pre-merge checks | βœ… 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title accurately reflects both main changes: showing deleted messages in channel preview and removing InjectedChannelInfo (the channel item redesign).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deleted-messages-in-channel-list

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nuno-vieira nuno-vieira changed the title Show deleted messages in channel preview and redesign swipe actions Show deleted messages in channel preview + missing channel item redesign Mar 27, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
DemoAppSwiftUI/PinChannelHelpers.swift (1)

95-126: ⚠️ Potential issue | 🟑 Minor

Keep the pinning demo row in sync with the framework row.

When isChannelPinningFeatureEnabled is on, this custom item is the one that gets rendered, but its subtitle/status logic still stops at draft/plain preview text. Unlike ChatChannelListItem, it never renders the deleted-message placeholder/icon or the failed-message badge, so the pinning demo path won't actually show the behavior this PR adds. Consider extracting the shared preview-state block instead of maintaining a second copy here.

Also applies to: 176-183

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@DemoAppSwiftUI/PinChannelHelpers.swift` around lines 95 - 126, The custom
pinning row's subtitle/status (in subtitleText and subtitleView) only handles
typing, draft and plain preview but misses deleted-message placeholder/icon and
failed-message badge that ChatChannelListItem shows; extract the shared
preview-state rendering logic used by ChatChannelListItem into a reusable helper
(e.g., a subtitleContent/subtitleView provider) and replace the duplicated logic
in PinChannelHelpers (subtitleText/subtitleView) so it: checks
shouldShowTypingIndicator, shows draft UI when draftMessageText exists, formats
previewMessage via utils.messagePreviewFormatter, and also renders
deleted-message placeholder/icon and the failed-message badge consistent with
ChatChannelListItem (including image/icon and SubtitleText usage).
🧹 Nitpick comments (1)
Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift (1)

544-550: Consider simplifying redundant conditions.

Both branches now call updateChannels(), making the conditional structure redundant. This could be simplified:

♻️ Suggested simplification
 private func handleChannelAppearance() {
-    if skippedChannelUpdates && selectedChannel == nil {
-        updateChannels()
-    } else if skippedChannelUpdates {
+    if skippedChannelUpdates {
         updateChannels()
     }
 }
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`
around lines 544 - 550, The conditional in handleChannelAppearance is redundant
because both branches call updateChannels(); replace the whole if/else structure
with a single condition that checks skippedChannelUpdates and calls
updateChannels() (retain use of skippedChannelUpdates and selectedChannel only
if needed elsewhere); update the function handleChannelAppearance to simply call
updateChannels() when skippedChannelUpdates is true to remove duplicate
branches.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListItem.swift`:
- Around line 253-268: lastMessageFailedToSend currently only checks
previewMessage?.localState == .sendingFailed, so .syncingFailed previews slip
through and cause shouldShowReadEvents to return true; update the logic in
lastMessageFailedToSend (used by shouldShowReadEvents) to treat .syncingFailed
the same as .sendingFailed (e.g., check for both states on
previewMessage?.localState) so MessageReadIndicatorView and subtitle rendering
hide failure affordances consistently when previewMessage.localState is
.sendingFailed or .syncingFailed.

---

Outside diff comments:
In `@DemoAppSwiftUI/PinChannelHelpers.swift`:
- Around line 95-126: The custom pinning row's subtitle/status (in subtitleText
and subtitleView) only handles typing, draft and plain preview but misses
deleted-message placeholder/icon and failed-message badge that
ChatChannelListItem shows; extract the shared preview-state rendering logic used
by ChatChannelListItem into a reusable helper (e.g., a
subtitleContent/subtitleView provider) and replace the duplicated logic in
PinChannelHelpers (subtitleText/subtitleView) so it: checks
shouldShowTypingIndicator, shows draft UI when draftMessageText exists, formats
previewMessage via utils.messagePreviewFormatter, and also renders
deleted-message placeholder/icon and the failed-message badge consistent with
ChatChannelListItem (including image/icon and SubtitleText usage).

---

Nitpick comments:
In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`:
- Around line 544-550: The conditional in handleChannelAppearance is redundant
because both branches call updateChannels(); replace the whole if/else structure
with a single condition that checks skippedChannelUpdates and calls
updateChannels() (retain use of skippedChannelUpdates and selectedChannel only
if needed elsewhere); update the function handleChannelAppearance to simply call
updateChannels() when skippedChannelUpdates is true to remove duplicate
branches.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bdc5d3e2-e888-4948-af48-88fed2245ba7

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 91bc787 and 7649d4c.

β›” Files ignored due to path filters (30)
  • Sources/StreamChatSwiftUI/Generated/L10n.swift is excluded by !**/generated/**
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_dmChannel.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_dmChannel.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_dmChannel.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_dmChannel.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_groupChannel.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_groupChannel.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_groupChannel.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_groupChannel.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_sentByCurrentUser.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_sentByCurrentUser.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_sentByCurrentUser.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_deletedMessage_sentByCurrentUser.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_emptyMessages.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_emptyMessages.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_emptyMessages.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_emptyMessages.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_ephemeralMessageSkipped_showsPreviousMessage.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_ephemeralMessageSkipped_showsPreviousMessage.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_ephemeralMessageSkipped_showsPreviousMessage.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_ephemeralMessageSkipped_showsPreviousMessage.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_giphyMessageLatestButPreviewIsAnotherMessage.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messageFailedToSend.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messageFailedToSend.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messageFailedToSend.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messageFailedToSend.small-dark.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messagePending.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messagePending.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messagePending.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannelList/__Snapshots__/ChatChannelListItemView_Tests/test_channelListItem_messagePending.small-dark.png is excluded by !**/*.png
πŸ“’ Files selected for processing (12)
  • DemoAppSwiftUI/PinChannelHelpers.swift
  • Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListItem.swift
  • Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift
  • Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelNavigatableListItem.swift
  • Sources/StreamChatSwiftUI/Resources/en.lproj/Localizable.strings
  • Sources/StreamChatSwiftUI/Utils/MessagePreviewFormatter.swift
  • StreamChatSwiftUI.xcodeproj/project.pbxproj
  • StreamChatSwiftUITests/Infrastructure/Shared/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerViewModel_Tests.swift
  • StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListItemView_Tests.swift
  • StreamChatSwiftUITests/Tests/ChatChannelList/ChatChannelListViewModel_Tests.swift
  • StreamChatSwiftUITests/Tests/Utils/MessagePreviewFormatter_Tests.swift
πŸ’€ Files with no reviewable changes (1)
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerViewModel_Tests.swift

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

Copy link
Copy Markdown
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, will do some tests next

@@ -545,11 +545,7 @@ import UIKit
if skippedChannelUpdates && selectedChannel == nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can now merge these 2 if statements though, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? πŸ€”

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you see it like this, you will know πŸ˜„

private func handleChannelAppearance() {
        if skippedChannelUpdates && selectedChannel == nil {
            updateChannels()
        } else if skippedChannelUpdates {
            updateChannels()
        }
    }

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah shiit XD, will fix this

}
}

private func updateSelectedChannelData() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was crazy. However, I believe we should test before iOS 16, when a navigation view is used. I think the screen was popped in some cases, which was why we had this stuff.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, @testableapple reminder to test this, I don't have a sim with this version, but if you don't have it as well, I'll install

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, what you can do instead is temporarily comment out the navigation stack code in NavigationContainerView and test with navigation view. You should force channel update from a channel that's not selected (just sending a channel in another channel should be fine).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested, and it all looks good πŸ‘ (But maybe still worth testing on iOS 16)

Update reference images to reflect channel list item changes
(deleted message display, swipe actions redesign, empty state text).
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift (1)

502-510: ⚠️ Potential issue | 🟑 Minor

Filter ephemeral messages for consistency with ChatChannelListItem.

The PR objectives specify that preview messages should skip ephemeral messages using first(where: { $0.type != .ephemeral }). ChatChannelListItem.swift implements this filtering (line 113), and there's a test confirming ephemeral messages should be skipped in channel list previews. However, the search results here use channel.latestMessages.first without filtering, which could display ephemeral messages in search result previews. Use the same filtering approach to maintain consistency.

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`
around lines 502 - 510, In ChatChannelListViewModel where searchResults is built
(the assignment creating ChannelSelectionInfo), change the message selection to
skip ephemeral messages the same way ChatChannelListItem does: instead of using
channel.latestMessages.first, use channel.latestMessages.first(where: { $0.type
!= .ephemeral }) so ChannelSelectionInfo.message excludes ephemeral previews and
remains consistent with ChatChannelListItem and existing tests.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`:
- Around line 544-548: The skippedChannelUpdates flag is never cleared after
queued updates are applied, causing repeated redundant updateChannels() calls;
after the updateChannels() call that applies queued changes (in the
selectedChannel willSet observer where handleChannelListChanges() set
skippedChannelUpdates = true), set skippedChannelUpdates = false so the
queued-update state is reset (alternatively you can clear it at the end of
handleChannelAppearance(), but prefer clearing it immediately after
updateChannels() in the willSet observer).

---

Outside diff comments:
In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`:
- Around line 502-510: In ChatChannelListViewModel where searchResults is built
(the assignment creating ChannelSelectionInfo), change the message selection to
skip ephemeral messages the same way ChatChannelListItem does: instead of using
channel.latestMessages.first, use channel.latestMessages.first(where: { $0.type
!= .ephemeral }) so ChannelSelectionInfo.message excludes ephemeral previews and
remains consistent with ChatChannelListItem and existing tests.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca046797-c1d0-4506-b650-a671c0e4610d

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 82c79e1 and 1863b7b.

πŸ“’ Files selected for processing (2)
  • CHANGELOG.md
  • Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift

Comment on lines 544 to 548
private func handleChannelAppearance() {
if skippedChannelUpdates && selectedChannel == nil {
if skippedChannelUpdates {
updateChannels()
} else if skippedChannelUpdates {
updateSelectedChannelData()
} else if !skippedChannelUpdates && selectedChannel != nil {
if selectedChannel?.injectedChannelInfo == nil {
selectedChannel?.injectedChannelInfo = InjectedChannelInfo(unreadCount: 0)
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for where skippedChannelUpdates is assigned
rg -n "skippedChannelUpdates\s*=" --type swift -C 2

# Check if the removed updateSelectedChannelData had reset logic (in git history)
git log -p --all -S "skippedChannelUpdates = false" -- "*.swift" 2>/dev/null | head -50

Repository: GetStream/stream-chat-swiftui

Length of output: 1310


🏁 Script executed:

# Search for all occurrences of skippedChannelUpdates (assignments, reads, resets)
rg -n "skippedChannelUpdates" --type swift -B 2 -A 2

# Look at the selectedChannel property definition and its observers
rg -n "@Published|selectedChannel|didSet|willSet" Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift -A 5

Repository: GetStream/stream-chat-swiftui

Length of output: 8436


Reset skippedChannelUpdates flag after applying queued updates.

The flag is set to true in handleChannelListChanges() at line 320, then checked in the selectedChannel willSet observer (line 60) when the channel is deselected. However, the flag is never reset to false after updateChannels() is called, which means subsequent handleChannelAppearance() invocations will redundantly call updateChannels() again.

Add skippedChannelUpdates = false after the updateChannels() call in the willSet observer (after line 61), or alternatively after the call in handleChannelAppearance() (after line 546). The former location is semantically more appropriate since that's where the "pop happened" and queued changes are actually applied.

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`
around lines 544 - 548, The skippedChannelUpdates flag is never cleared after
queued updates are applied, causing repeated redundant updateChannels() calls;
after the updateChannels() call that applies queued changes (in the
selectedChannel willSet observer where handleChannelListChanges() set
skippedChannelUpdates = true), set skippedChannelUpdates = false so the
queued-update state is reset (alternatively you can clear it at the end of
handleChannelAppearance(), but prefer clearing it immediately after
updateChannels() in the willSet observer).

Co-authored-by: Stream Bot <ci@getstream.io>
@Stream-SDK-Bot
Copy link
Copy Markdown
Collaborator

SDK Size

title develop branch diff status
StreamChatSwiftUI 8.67 MB 7.97 MB -724 KB πŸš€

@Stream-SDK-Bot
Copy link
Copy Markdown
Collaborator

StreamChatSwiftUI XCSize

Object Diff (bytes)
ChatChannelHeaderViewModifier.o -90228
ChatChannelSwipeableListItem.o -87608
ChatChannelListViewModel.o -67424
MessageItemView.o -64396
PinnedMessagesView.o -61768
Show 24 more objects
Object Diff (bytes)
ChatThreadListNavigatableItem.o -54796
MessageListView.o -37028
MoreChannelActionsView.o -35120
ReactionsOverlayView.o -34600
ChatChannelNavigatableListItem.o -30908
MessageContainerView.o -30668
MessageTopView.o -29960
MessageRepliesView.o -29808
TypingIndicatorView.o -29168
ChatChannelListItem.o -27119
DefaultChannelActions.o -5504
DefaultViewFactory.o -4044
ChatChannelInfoView.o -2740
MediaAttachmentsView.o -1376
ChatChannelList.o -1368
FileAttachmentsView.o -1360
ChatChannelListView.o -1356
ChatThreadList.o -1292
MessagePreviewFormatter.o +872
ChatChannelInfoViewModel.o -90
AttachmentMediaPickerItemView.o -72
SelectionBadgeView.o -52
DismissButtonOverlayModifier.o +48
ComposerFileAttachmentView.o -44

@github-actions
Copy link
Copy Markdown

Public Interface

- public final class InjectedChannelInfo: Sendable  
- 
-   public let subtitle: String?
-   public let unreadCount: Int
-   public let timestamp: String?
-   public let lastMessageAt: Date?
-   public let latestMessages: [ChatMessage]?
-   
- 
-   public init(subtitle: String? = nil,unreadCount: Int,timestamp: String? = nil,lastMessageAt: Date? = nil,latestMessages: [ChatMessage]? = nil)

 public struct ChatChannelListItem: View  
-   public init(factory: Factory = DefaultViewFactory.shared,channel: ChatChannel,channelName: String,injectedChannelInfo: InjectedChannelInfo? = nil,disabled: Bool = false,onItemTap: @escaping (ChatChannel) -> Void)
+   public init(factory: Factory = DefaultViewFactory.shared,channel: ChatChannel,channelName: String,isSelected: Bool = false,disabled: Bool = false,onItemTap: @escaping (ChatChannel) -> Void)

 public final class ChannelSelectionInfo: Identifiable, @unchecked Sendable  
-   public var injectedChannelInfo: InjectedChannelInfo?
+   public let searchType: ChannelListSearchType
-   public let searchType: ChannelListSearchType
+   
-   
+ 
- 
+   public init(channel: ChatChannel,message: ChatMessage?,searchType: ChannelListSearchType = .messages)
-   public init(channel: ChatChannel,message: ChatMessage?,searchType: ChannelListSearchType = .messages)

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants