Skip to content

Add support for rendering messages from the top of the list#1530

Open
nuno-vieira wants to merge 26 commits into
developfrom
add/message-start-from-top-support
Open

Add support for rendering messages from the top of the list#1530
nuno-vieira wants to merge 26 commits into
developfrom
add/message-start-from-top-support

Conversation

@nuno-vieira

@nuno-vieira nuno-vieira commented Jul 14, 2026

Copy link
Copy Markdown
Member

πŸ”— Issue Links

Resolves IOS-1058

🎯 Goal

Add support for rendering messages from the top of the list.

πŸ“ Summary

  • Add MessageListConfig.shouldMessagesStartAtTheTop (defaults to false, fully opt-in)
  • When enabled and the messages are shorter than the visible list, messages are laid out from the top with the remaining space acting as an implicit bottom spacer
  • Once messages grow past the visible height, the list behaves exactly like the existing scrollable inverted list, including regular scroll/insertion animations
  • Add a "Messages Start at the Top" toggle to the demo app's App Configuration screen

πŸ›  Implementation

  • The message stack is given a minHeight equal to the available list height and bottom-aligned; after the list's upside-down flip this places the messages at the top
  • The available height is measured synchronously via a GeometryReader wrapping the list content, so the top-aligned frame never lags behind the real viewport size on first layout
  • Once the messages outgrow the viewport the minHeight clamp has no effect by construction, so the list naturally degrades to the regular inverted behavior with no extra state to track
  • While top-aligned, animations are suppressed for the whole scroll view on content updates, since animating the row insertion and the spacer's resize as two separate animations made existing messages look like they were shifting instead of a new message simply appearing

🧷 Scroll stability while rubber-banding

With few messages, dragging the top-aligned list up rubber-bands the rows under the navigation bar. When the rows are hosted in a LazyVStack, that overscroll triggers a layout invalidation mid-gesture: the scroll view clamps the drag and the messages visibly jump back. The lazy container was isolated empirically as the cause β€” the jump reproduces with every scroll callback and preference handler in the list disabled, only with two or more messages, and never with an eager container. The exact trigger is internal to the lazy layout (it sizes and places children relative to the visible region, and an overscrolled, flipped, height-clamped viewport puts that machinery in an edge case), so the safe conclusion is behavioral: eager rendering of the visible rows keeps the layout stable during rubber-banding; a lazy one doesn't. Two solutions were explored; both fix the jump and both were validated with the same drag/hold E2E scenarios (including live message events arriving mid-drag).

1. Container swap β€” currently used

The message stack renders as an eager VStack while top-aligned with fewer than 20 messages, and as the regular LazyVStack otherwise. 20 messages always overflow the viewport, so beyond that top alignment (and the jump) is irrelevant.

  • βœ… Simple and easy to reason about: short lists are fully eager, long lists are exactly the existing lazy list
  • βœ… No laziness bookkeeping at all while the feature is visually active
  • ⚠️ Crossing the 20-message threshold swaps the container type, which resets the view identity of the whole stack once (a one-time reflow with no row state to lose in practice)
  • ⚠️ Eager rendering cost is bounded but real if rows are heavy (attachments), though capped at 20 rows

2. Eager chunk inside the lazy stack β€” explored and reverted (d3737ed7, reverted in ba0d5e85)

The container stays a LazyVStack always; the newest 20 rows are grouped into a single plain VStack child, with older history remaining individual lazy rows. A lazy stack manages its children per direct child, so the chunk is laid out as one opaque unit with no lazy-layout boundaries inside it β€” which was verified to keep the layout stable during overscroll, same as the full container swap.

  • βœ… No container swap: the outer stack's identity is stable at every message count
  • βœ… Older history in long channels stays lazy; crossing the threshold only re-identifies one row at a time (the row leaving the chunk) instead of the whole list
  • ⚠️ Hackier structure: it relies on the (undocumented but long-standing) per-child realization semantics of lazy stacks, and splits the rows across two ForEaches with a nested container in between
  • ⚠️ Every new message migrates the 20th row from the eager chunk to the lazy ForEach, so its structural identity churns continuously as the conversation grows

The container swap was kept because its complexity is front-loaded and obvious (one if around the container), while the chunk approach spreads subtle identity implications across the list body. If the one-time reflow at the threshold ever becomes noticeable, the chunk approach is a validated drop-in alternative.

🎨 Showcase

Few messages render at the top of the list instead of the bottom, with the remaining space kept empty below them.

πŸ§ͺ Manual Testing Notes

  • Enable "Messages Start at the Top" in the demo app's App Configuration screen
  • Open a channel with few messages and confirm they render at the top, not the bottom
  • Send messages until the list fills the screen and confirm it smoothly transitions to normal scrollable behavior
  • Open/close the keyboard and the attachment picker and confirm the messages never shift or scroll under the navigation bar
  • Scroll/rubber-band the top-aligned list up and down and confirm the drag never clamps or jumps, including while another participant sends a message mid-drag
  • Repeat the above with the glass/floating composer style enabled

β˜‘οΈ 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

    • Added an option to start message lists at the top when conversations contain few messages.
    • Added a Message List setting in the demo app to enable or disable top-aligned messages.
    • Preserved appropriate spacing and scrolling behavior for short and long conversations.
  • Documentation

    • Documented the new message list configuration option in the upcoming changelog.

@nuno-vieira
nuno-vieira requested a review from a team as a code owner July 14, 2026 14:30
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▢️ Resume reviews
  • βœ… Review completed - (πŸ”„ Check again to review again)
πŸ“ Walkthrough

Walkthrough

Changes

Adds a public MessageListConfig option for top-aligning short message lists, wires it into the demo configuration UI, implements height-aware layout and scrolling behavior, and adds snapshot coverage for short and long message lists.

Top-aligned message list

Layer / File(s) Summary
Configuration and demo-app wiring
Sources/StreamChatSwiftUI/ChatMessageList/MessageListConfig.swift, DemoAppSwiftUI/AppConfiguration/*, CHANGELOG.md
Adds shouldMessagesStartAtTheTop, exposes it in the demo settings, injects it into MessageListConfig, and documents the option.
Top-aligned message list layout
Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift, Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift
Measures natural content height, applies conditional minimum height and alignment, and updates scroll-button, anchor, animation, and padding behavior.
Top-alignment snapshot validation
StreamChatSwiftUITests/Tests/ChatChannel/MessageListView_Tests.swift
Adds snapshots for few messages, bottom-inset layouts, and many messages with top alignment enabled.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AppConfigurationView
  participant AppConfiguration
  participant MessageListConfig
  participant MessageListView
  participant ScrollView
  AppConfigurationView->>AppConfiguration: persist messagesStartAtTheTop
  AppConfiguration->>MessageListConfig: build configured message-list settings
  MessageListConfig->>MessageListView: enable top-alignment mode
  MessageListView->>ScrollView: measure content and apply top-aligned layout
Loading

Suggested reviewers: martinmitrevski, laevandus

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly matches the main change: adding opt-in support for top-aligned message rendering.
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add/message-start-from-top-support

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.

When enabled and the messages are shorter than the visible list, they
are laid out from the top instead of the bottom, matching the UIKit
SDK's Components.shouldMessagesStartAtTheTop. Once the messages grow
past the visible height, the list behaves like a regular inverted
message list again.
@nuno-vieira
nuno-vieira force-pushed the add/message-start-from-top-support branch from 16ad1f2 to 8c81f31 Compare July 14, 2026 14:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift`:
- Around line 340-345: Update the message item transition near the list item’s
.id in MessageListView so it uses the dynamic top-aligned state,
topAlignedMinHeight, rather than the static
messageListConfig.shouldMessagesStartAtTheTop flag. Preserve identity
transitions only while top-aligned mode is active, and use the normal opacity
transition once content overflows and topAlignedMinHeight is nil.
πŸͺ„ 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: 2c6d85d0-d03e-45f7-98d4-ad1bf79e42c3

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 3ca1ae4 and 16ad1f2.

β›” Files ignored due to path filters (3)
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessages.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessagesWithBottomInset.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_manyMessages.1.png is excluded by !**/*.png
πŸ“’ Files selected for processing (7)
  • CHANGELOG.md
  • DemoAppSwiftUI/AppConfiguration/AppConfiguration.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfigurationView.swift
  • Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListConfig.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageListView_Tests.swift

Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated
Add top padding to keep the first message clear of the navigation bar
when the list is top-aligned, and extract the scroll anchors into
named topAnchorView/bottomAnchorView view properties.
Rename topAnchor/bottomAnchor to topAnchorId/bottomAnchorId, move them
back next to scrollAreaId, and document bottomAnchorView to match
topAnchorView.
@nuno-vieira
nuno-vieira force-pushed the add/message-start-from-top-support branch from 932d069 to 2a779ce Compare July 14, 2026 15:12
Key the message row's transition off the dynamic top-aligned regime
instead of the static shouldMessagesStartAtTheTop flag, so the default
insertion/removal fade returns once a channel's messages grow past
the visible height.
Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift (2)

343-347: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | πŸ’€ Low value

Allow messageListContentHeight to reset cleanly.

Using if let value drops the nil default value that the preference key emits when the tracking modifier is disabled dynamically. While harmless right now (because resolveTopAlignedMinHeight guards against the config flag being false), removing the optional binding maintains cleaner state hygiene.

♻️ Proposed fix
-                .onPreferenceChange(MessageListContentHeightPreferenceKey.self) { value in
-                    if let value, value != messageListContentHeight {
-                        messageListContentHeight = value
-                    }
-                }
+                .onPreferenceChange(MessageListContentHeightPreferenceKey.self) { value in
+                    if value != messageListContentHeight {
+                        messageListContentHeight = value
+                    }
+                }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift` around lines
343 - 347, Update the onPreferenceChange handler for
MessageListContentHeightPreferenceKey to assign the emitted optional value
directly to messageListContentHeight, allowing it to reset to nil when tracking
is disabled; retain the existing change guard only if it supports optional
equality without preventing that reset.

596-601: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | πŸ’€ Low value

Remove unused topAnchorView.

topAnchorId and topAnchorView are defined and placed in the layout, but they are never referenced for scrolling or any other logic. Since top alignment is achieved purely through layout modifiers, this view is unused and can be removed.

♻️ Proposed fix
-    private var topAnchorView: some View {
-        Color.clear
-            .frame(height: 0)
-            .id(topAnchorId)
-            .accessibilityHidden(true)
-    }

You can also safely remove the topAnchorId declaration at line 82 and the topAnchorView usage inside the LazyVStack at line 211.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift` around lines
596 - 601, Remove the unused topAnchorView property, its topAnchorView placement
in the LazyVStack, and the associated topAnchorId declaration; leave the
existing layout modifiers and top-alignment behavior unchanged.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Line 6: Update the β€œβœ… Added” heading in CHANGELOG.md from level three to level
two so it follows the top-level β€œ# Upcoming” heading correctly.

In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift`:
- Around line 590-592: Update the overflow check in the top-aligned layout logic
to compare contentHeight directly against containerHeight. Remove the
bottomInset subtraction while preserving the existing nil-return behavior when
contentHeight exceeds the available container height.

---

Nitpick comments:
In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift`:
- Around line 343-347: Update the onPreferenceChange handler for
MessageListContentHeightPreferenceKey to assign the emitted optional value
directly to messageListContentHeight, allowing it to reset to nil when tracking
is disabled; retain the existing change guard only if it supports optional
equality without preventing that reset.
- Around line 596-601: Remove the unused topAnchorView property, its
topAnchorView placement in the LazyVStack, and the associated topAnchorId
declaration; leave the existing layout modifiers and top-alignment behavior
unchanged.
πŸͺ„ 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: 29d40160-1af8-4425-91fd-e2274501ce50

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 16ad1f2 and c0ad74c.

β›” Files ignored due to path filters (3)
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessages.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessagesWithBottomInset.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_manyMessages.1.png is excluded by !**/*.png
πŸ“’ Files selected for processing (7)
  • CHANGELOG.md
  • DemoAppSwiftUI/AppConfiguration/AppConfiguration.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfigurationView.swift
  • Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListConfig.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageListView_Tests.swift
🚧 Files skipped from review as they are similar to previous changes (5)
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListConfig.swift
  • Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfiguration.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfigurationView.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageListView_Tests.swift

Comment thread CHANGELOG.md
Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated

@martinmitrevski martinmitrevski left a comment

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.

fine with the code changes if it's the only way - but @testableapple should run a solid QA. Also, would be nice to measure the performance, we put another geometry reader, plus some additional ifs, anchors etc.

Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated
Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated
Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated
Comment thread Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift Outdated
The topmost message's spacing was keyed off the dynamically resolved
top-aligned height, which itself depended on the measured content height,
causing the content height preference to update multiple times per frame.
Key the spacing off the static configuration flag instead to break the loop.
Move the combined date/separator overlay spacing and top-of-list spacing
out of an inline nested expression into a named helper for readability.

@laevandus laevandus left a comment

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.

I did some testing and works well. The initial shift of the whole message list is fixed as well. Only other alternative I could think of was dropping flipped handling for bottom alignment, but then many VStacks and message index handling logic needs to be updated as well (messagingOrder would change and then index logic does not match anymore). That seems like a much bigger change than what we have here. Therefore, I feel like we should go with this implementation if we don't find any other layout issues during testing.

@martinmitrevski martinmitrevski left a comment

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.

LGTM βœ… important one for @testableapple, both cases should be tested - starting from top and bottom

When messages fit on screen there is nothing to scroll, so keep the
scrollbar hidden to match the UIKit message list behavior.
Insert a trailing spacer in the flipped stack so it becomes leading
space under the navigation bar, keeping the time bubble from sitting
flush against it.
@nuno-vieira
nuno-vieira force-pushed the add/message-start-from-top-support branch from a32eab5 to 81caf67 Compare July 16, 2026 10:30
Replace the fits/overflow preference regime with a fill + UIKit clamp that
pins short content without feeding layout feedback into SwiftUI, and latch
insert animations once the list overflows to avoid boundary freezes.
Keep the minHeight fill approach, but never gate GeometryReader height on
fits, latch overflow animations/indicators one-way, skip auto-scrollTo
newest while fitting, and defer content-height preference updates.
nuno-vieira and others added 10 commits July 16, 2026 18:13
Reinstate the UIKit scroll clamp that pins short (fitting) content to the
visual top, but never disable scrolling or bouncing so the list can always
be dragged. Remove the now-unused content-height preference key.
Replace the UIKit scroll-clamp bridge, forced scroll bounce, and
top-aligned regime latches with a pure-SwiftUI fill. Short message lists
now rest naturally at the top instead of being pinned by a UIScrollView
bridge, removing the freeze and layout feedback loops.

Also skip message insertion/removal animations while messages start at
the top, so sending a message no longer shifts the whole list.

Re-record the top-aligned snapshots to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This reverts commit d3737ed.
@github-actions

Copy link
Copy Markdown

Public Interface

 @MainActor public final class MessageListConfig  
-   
+   public let shouldMessagesStartAtTheTop: Bool
- 
+   
-   public init(messageListType: MessageListType = .messaging,typingIndicatorPlacement: TypingIndicatorPlacement = .automatic,groupMessages: Bool = true,messageDisplayOptions: MessageDisplayOptions = MessageDisplayOptions(),messagePaddings: MessagePaddings = MessagePaddings(),dateIndicatorPlacement: DateIndicatorPlacement = .messageList,pageSize: Int = 25,messagePopoverEnabled: Bool = true,doubleTapOverlayEnabled: Bool = false,becomesFirstResponderOnOpen: Bool = false,resignsFirstResponderOnScrollDown: Bool = true,updateChannelsFromMessageList: Bool = false,maxTimeIntervalBetweenMessagesInGroup: TimeInterval = 60,cacheSizeOnChatDismiss: Int = 1024 * 1024 * 100,iPadSplitViewEnabled: Bool = true,scrollingAnchor: UnitPoint = .center,showNewMessagesSeparator: Bool = true,highlightMessageWhenJumping: Bool = true,handleTabBarVisibility: Bool = true,messageListAlignment: MessageListAlignment = .standard,uniqueReactionsEnabled: Bool = false,localLinkDetectionEnabled: Bool = true,isMessageEditedLabelEnabled: Bool = true,markdownSupportEnabled: Bool = false,userBlockingEnabled: Bool = true,bouncedMessagesAlertActionsEnabled: Bool = true,skipEditedMessageLabel: @escaping (ChatMessage) -> Bool = { _ in false },draftMessagesEnabled: Bool = true,hidesCommandsOverlayOnMessageListTap: Bool = true,hidesAttachmentsPickersOnMessageListTap: Bool = true,attachmentPreviewWidth: CGFloat = 256,videoAttachmentCachingPolicy: VideoAttachmentCachingPolicy? = nil,navigationBarDisplayMode: NavigationBarItem.TitleDisplayMode = .inline,supportedMessageActions: @escaping @MainActor (SupportedMessageActionsOptions) -> [MessageAction] = { MessageAction.defaultActions(for: $0) })
+ 
+   public init(messageListType: MessageListType = .messaging,typingIndicatorPlacement: TypingIndicatorPlacement = .automatic,groupMessages: Bool = true,messageDisplayOptions: MessageDisplayOptions = MessageDisplayOptions(),messagePaddings: MessagePaddings = MessagePaddings(),dateIndicatorPlacement: DateIndicatorPlacement = .messageList,pageSize: Int = 25,messagePopoverEnabled: Bool = true,doubleTapOverlayEnabled: Bool = false,becomesFirstResponderOnOpen: Bool = false,resignsFirstResponderOnScrollDown: Bool = true,updateChannelsFromMessageList: Bool = false,maxTimeIntervalBetweenMessagesInGroup: TimeInterval = 60,cacheSizeOnChatDismiss: Int = 1024 * 1024 * 100,iPadSplitViewEnabled: Bool = true,scrollingAnchor: UnitPoint = .center,showNewMessagesSeparator: Bool = true,highlightMessageWhenJumping: Bool = true,handleTabBarVisibility: Bool = true,messageListAlignment: MessageListAlignment = .standard,uniqueReactionsEnabled: Bool = false,localLinkDetectionEnabled: Bool = true,isMessageEditedLabelEnabled: Bool = true,markdownSupportEnabled: Bool = false,userBlockingEnabled: Bool = true,bouncedMessagesAlertActionsEnabled: Bool = true,skipEditedMessageLabel: @escaping (ChatMessage) -> Bool = { _ in false },draftMessagesEnabled: Bool = true,hidesCommandsOverlayOnMessageListTap: Bool = true,hidesAttachmentsPickersOnMessageListTap: Bool = true,attachmentPreviewWidth: CGFloat = 256,videoAttachmentCachingPolicy: VideoAttachmentCachingPolicy? = nil,navigationBarDisplayMode: NavigationBarItem.TitleDisplayMode = .inline,supportedMessageActions: @escaping @MainActor (SupportedMessageActionsOptions) -> [MessageAction] = { MessageAction.defaultActions(for: $0) },shouldMessagesStartAtTheTop: Bool = false)

@Stream-SDK-Bot

Copy link
Copy Markdown
Collaborator

SDK Size

title develop branch diff status
StreamChatSwiftUI 6.15 MB 6.17 MB +18 KB 🟒

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift`:
- Around line 812-820: The insert/remove suppression in the change-handling
switch should apply only while the channel is currently using the few-message
top-aligned layout, not whenever
utils.messageListConfig.shouldMessagesStartAtTheTop is enabled. Update the guard
around the .insert and .remove cases to use the existing current-layout or
message-count condition that identifies that eager top-aligned regime,
preserving animations after the list transitions to the normal lazy/inverted
layout.
πŸͺ„ 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: 235a956a-1dfc-49f1-84c2-4d102104a265

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 9ae163e and 3c435ba.

β›” Files ignored due to path filters (3)
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessages.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_fewMessagesWithBottomInset.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageListView_Tests/test_messageListView_shouldMessagesStartAtTheTop_manyMessages.1.png is excluded by !**/*.png
πŸ“’ Files selected for processing (4)
  • DemoAppSwiftUI/AppConfiguration/AppConfiguration.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfigurationView.swift
  • Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageListView.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • DemoAppSwiftUI/AppConfiguration/AppConfiguration.swift
  • DemoAppSwiftUI/AppConfiguration/AppConfigurationView.swift

Comment thread Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift
@Stream-SDK-Bot

Copy link
Copy Markdown
Collaborator

StreamChatSwiftUI XCSize

Object Diff (bytes)
MessageListView.o +14654
MessageListConfig.o +188
ChatChannelViewModel.o -44

@sonarqubecloud

Copy link
Copy Markdown

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants