Skip to content

Merge develop to v7 (17.03.2026)#6262

Merged
VelikovPetar merged 38 commits intov7from
merge/develop_to_v7_20260317
Mar 18, 2026
Merged

Merge develop to v7 (17.03.2026)#6262
VelikovPetar merged 38 commits intov7from
merge/develop_to_v7_20260317

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented Mar 17, 2026

Goal

Merge develop to v7

Implementation

Merge develop to v7

Testing

Everything should work

Summary by CodeRabbit

Release Notes

  • New Features

    • Configurable back button behavior for ChannelsScreen via new isBackPressEnabled parameter
    • Header and footer content support in message list display
    • Async image header injection for authenticated image requests
    • Cursor-based pagination for message search (replaces offset-based approach)
    • Delivery receipts privacy setting support
  • Bug Fixes

    • Allow offset parameter with sort in message search queries
    • Improved deleted message handling in reply capability checks
  • Chores

    • Updated GitHub Actions workflows to v0.9.0
    • Project version bumped to 6.35.0
    • Restricted file storage access paths

aleksandar-apostolov and others added 30 commits February 13, 2026 14:01
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
)

* Ensure AttachmentsPickerViewModel.isShowingAttachments is preserved across process death.

* Fix CaptureMediaContract not preserved across activity death.

* Remove logs.

* Introduce `CaptureMediaContract.restoreFilePaths` method.
* Fix delete message not working when offline (SYNC_NEEDED)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update DeleteMessageListener tests for SYNC_NEEDED remote delete

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
…#6166)

* feat: add support for `headingContent` and `footerContent` slots to `Messages`

* refactor: address review comments

* chore: run `./gradlew apiDump spotlessApply`

---------

Co-authored-by: Petar Velikov <petarvelikov95@gmail.com>
* Fix incorrect validation for searchMessages parameters

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix detekt.

---------

Co-authored-by: Claude <noreply@anthropic.com>
* Use cursor-based pagination for search messages

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix detekt.

* Make next internal

---------

Co-authored-by: Claude <noreply@anthropic.com>
…ViewModelFactory` (#6187)

* Use cursor-based pagination for search messages

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix detekt.

* Add messageSearchSort option to ChannelListViewModel and ChannelViewModelFactory

Co-Authored-By: Claude <noreply@anthropic.com>

* Add tests for messageSearchSort in ChannelListViewModel

Co-Authored-By: Claude <noreply@anthropic.com>

* Make next internal

* Add messageSearchSort to logs

* detekt

* detekt

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: adasiewiczr <17440581+adasiewiczr@users.noreply.github.com>
…aders (#6203)

* Introduce AsyncImageHeadersProvider.

* Introduce AsyncImageHeadersProvider.

* Update KDocs

* Set interceptorCoroutineContext
* Disable swipe-to-reply for deleted messages

Co-Authored-By: Claude <noreply@anthropic.com>

* PR remarks.

---------

Co-authored-by: Claude <noreply@anthropic.com>
…ng channel queries (#6231)

Co-authored-by: Claude <noreply@anthropic.com>
* Fix wrong message type for commands in getMessageType()

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix KDoc

---------

Co-authored-by: Claude <noreply@anthropic.com>
github-actions Bot and others added 3 commits March 13, 2026 17:48
# Conflicts:
#	metrics/size.json
#	stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerState.kt
#	stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt
#	stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogicTest.kt
#	stream-chat-android-client/src/test/java/io/getstream/chat/android/client/utils/message/MessageUtilsTest.kt
#	stream-chat-android-compose/api/stream-chat-android-compose.api
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/factory/AttachmentsPickerMediaCaptureTabFactory.kt
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/media/CaptureMediaLauncher.kt
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageItem.kt
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatTheme.kt
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/messages/AttachmentsPickerViewModel.kt
#	stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt
#	stream-chat-android-docs/src/main/kotlin/io/getstream/chat/docs/kotlin/compose/messages/MessageComposer.kt
#	stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/contract/internal/CaptureMediaContract.kt
#	stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt
@VelikovPetar VelikovPetar requested a review from a team as a code owner March 17, 2026 12:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 17, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@VelikovPetar VelikovPetar added the pr:internal Internal changes / housekeeping label Mar 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 17, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.70 MB 0.45 MB 🟡
stream-chat-android-ui-components 10.60 MB 11.00 MB 0.41 MB 🟡
stream-chat-android-compose 12.81 MB 12.13 MB -0.68 MB 🚀

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 17, 2026

Walkthrough

This PR introduces cursor-based message pagination, refactors message deletion logic with a new shouldDeleteRemote check, adds delivery receipts support to privacy settings, implements async image headers for Coil integration, and updates GitHub Actions workflows to v0.9.0. Version bumped to 6.35.0.

Changes

Cohort / File(s) Summary
GitHub Workflows
.github/workflows/pr-checks.yml, pr-cleanup.yaml, pr-quality.yml, publish-new-version.yml, sdk-size-checks.yml, sdk-size-updates.yml
Updated workflow and action references from v0.6.1–v0.8.0 to v0.9.0.
Build & Version
gradle.properties, build.gradle.kts, README.md
Bumped project version to 6.35.0, added repositoryName configuration, updated compose module badge.
Message Deletion Refactoring
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/.../DeleteMessageListenerDatabase.kt, DeleteMessageListenerState.kt
Reworked precondition logic to use new shouldDeleteRemote() check, removing direct moderation error handling and altering control flow for local/remote delete decisions.
shouldDeleteRemote Logic
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt
Added public extension function Message.shouldDeleteRemote(currentUserId) that returns Result indicating whether remote deletion is permitted based on moderation, message type, and sync status.
Message Search Pagination
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt, stream-chat-android-ui-components/src/main/kotlin/.../SearchViewModel.kt
Replaced offset-based pagination with cursor-based (next) pagination; simplified offset validation to only reject offset+next combination; updated searchMessages to return SearchMessagesResult with next cursor.
Privacy Settings & Delivery Receipts
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt, socket/SocketFactory.kt
Added DeliveryReceipts mapping to DTO and PrivacySettings; updated socket factory to encode delivery_receipts in privacy settings JSON.
Async Image Headers Provider
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/helper/AsyncImageHeadersProvider.kt, stream-chat-android-compose/src/main/java/.../ImageHeadersInterceptor.kt
Introduced new AsyncImageHeadersProvider interface for suspend-based async header retrieval and ImageHeadersInterceptor to inject headers into Coil requests.
Coil Image Loader Factory
stream-chat-android-ui-common/src/main/kotlin/.../StreamImageLoaderFactory.kt, stream-chat-android-compose/src/main/java/.../StreamCoilImageLoaderFactory.kt
Added overloaded constructors accepting List\<Interceptor\> to support interceptor injection; updated component registration to use Dispatchers.IO context.
ChatTheme Updates
stream-chat-android-compose/src/main/java/.../ChatTheme.kt
Added asyncImageHeadersProvider parameter for async header injection; deprecated old ImageHeadersProvider path; introduced ImageHeadersInterceptor integration.
Compose UI Composables
stream-chat-android-compose/src/main/java/.../ChannelsScreen.kt, Messages.kt, MessageContainer.kt
Added isBackPressEnabled parameter to ChannelsScreen; added headerContent/footerContent to Messages; converted SwipeToReply isSwipeable from lambda to Boolean.
Channel/Message View Models
stream-chat-android-compose/src/main/java/.../ChannelListViewModel.kt, ChannelViewModelFactory.kt, AttachmentsPickerViewModel.kt
Added messageSearchSort parameter to ChannelListViewModel and factory for server-side sort; replaced offset pagination with sort/next; added @JvmOverloads to AttachmentsPickerViewModel.
Query Channels Logic
stream-chat-android-client/src/main/java/.../QueryChannelsLogic.kt
Replaced hard-coded MESSAGE_LIMIT and MEMBER_LIMIT with dynamic values from current request state.
Message Type Classification
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/internal/MessageUtils.kt
Removed command-based EPHEMERAL type detection; now only classifies messages with pending-upload attachments as EPHEMERAL; removed COMMAND_PATTERN regex.
File Path Configuration
stream-chat-android-ui-common/src/main/res/xml/stream_filepaths.xml
Removed broad path declarations; replaced with explicit external_pictures and external_movies paths.
Capabilities Helper
stream-chat-android-ui-common/src/main/kotlin/.../CapabilitiesHelper.kt
Added guard check for deleted messages in canReplyToMessage via !message.isDeleted().
Message Deletion Tests
stream-chat-android-client/src/test/java/.../DeleteMessageListenerDatabaseTest.kt, DeleteMessageListenerStateTest.kt, ChatClientGeneralApiTests.kt
Expanded test coverage for onMessageDeletePrecondition with multiple deletion scenarios (moderation bounce, error type, ephemeral, sync states); updated error message expectations.
Search & Pagination Tests
stream-chat-android-ui-components/src/test/kotlin/.../SearchViewModelTest.kt, QueryChannelsLogicTest.kt, ChannelListViewModelTest.kt
Added comprehensive tests for cursor-based pagination, next-token handling, and messageSearchSort wiring; added Fixture helpers for test setup.
Coil & Headers Tests
stream-chat-android-client/src/test/java/.../SocketFactoryTest.kt, DtoMappingTest.kt
Extended test data for privacy settings with deliveryReceipts scenarios; updated buildFullUserJson to include privacy_settings structure.
Message Utilities Tests
stream-chat-android-client/src/test/java/.../MessageUtilsTest.kt, stream-chat-android-compose/src/test/kotlin/.../MessageOptionItemVisibilityTest.kt
Removed testCommandMessage; added shouldDeleteRemote tests covering moderation, type, sync status failures and successes; extended canReplyToMessage test coverage.
Detekt Configuration
stream-chat-android-ui-components/detekt-baseline.xml
Removed ForbiddenComment suppression for pagination TODO in SearchViewModel.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

pr:new-feature, released

Suggested reviewers

  • andremion

Poem

🐰 Pagination hops with cursor feet,
Remote deletes no longer repeat—
Headers flow async through Coil's keen sight,
Privacy receipts shining bright!
From offset to next, our queries take flight! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and lacks required template sections; it only provides basic Goal/Implementation/Testing information without UI changes, detailed testing instructions, checklists, or structured content matching the repository template. Expand the description to follow the template structure: add detailed Implementation, Testing sections with patch details if needed, UI Changes with screenshots if applicable, and complete both Contributor and Reviewer checklists for thorough documentation.
Docstring Coverage ⚠️ Warning Docstring coverage is 19.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the merge operation between develop and v7 branches with a specific date stamp, clearly communicating the main change.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch merge/develop_to_v7_20260317
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can enforce grammar and style rules using `languagetool`.

Configure the reviews.tools.languagetool setting to enable/disable rules and categories. Refer to the LanguageTool Community to learn more.

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: 2

Caution

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

⚠️ Outside diff range comments (2)
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt (1)

1753-1757: ⚠️ Potential issue | 🟡 Minor

searchMessages KDoc no longer matches runtime validation.

Line [1769] allows offset + sort, but Line [1753] and Line [1756] still document that as invalid.

📝 Suggested KDoc patch
- * `@param` offset Pagination offset, cannot be used with sort or next.
+ * `@param` offset Pagination offset, cannot be used with next.
...
- * `@param` next Pagination parameter, cannot be used with non-zero offset.
- * `@param` sort The sort criteria applied to the result, cannot be used with non-zero offset.
+ * `@param` next Pagination parameter, cannot be used with offset.
+ * `@param` sort The sort criteria applied to the result.

As per coding guidelines **/*.kt: "Document public APIs with KDoc, including thread expectations and state notes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt`
around lines 1753 - 1757, Update the KDoc for the public function searchMessages
to match runtime validation: change the `@param` lines so offset is documented as
only incompatible with next (remove the "cannot be used with sort or next"
wording), document that sort may be used together with offset, and keep next
documented as "cannot be used with non-zero offset"; ensure the KDoc entries for
offset, limit, next, and sort reflect these exact compatibility rules and
mention any thread/state expectations present on the public searchMessages API.
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt (1)

362-363: ⚠️ Potential issue | 🟡 Minor

Minor typo in log message.

The log message uses the literal string 'query' instead of the variable $query.

Proposed fix
-        logger.v { "[loadMoreQueryMessages] query: 'query'" }
+        logger.v { "[loadMoreQueryMessages] query: '$query'" }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt`
around lines 362 - 363, The verbose log in loadMoreQueryMessages is printing the
literal string 'query' instead of the variable value; update the logger.v call
that references currentState.query (variable name query) to interpolate or
concatenate the actual query variable (e.g., include query) so the log shows the
real query content when calling logger.v in ChannelListViewModel.
🧹 Nitpick comments (6)
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientGeneralApiTests.kt (1)

235-235: Use backtick test naming for the renamed test.

Please align this changed test name with the repository test naming style.

✏️ Suggested rename
-    fun searchMessagesWithNextAndSort() = runTest {
+    fun `search messages with next and sort`() = runTest {

As per coding guidelines **/src/test/**/*.kt: "Use backtick test names (for example: fun message list filters muted channels()) for readability".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientGeneralApiTests.kt`
at line 235, Rename the test function searchMessagesWithNextAndSort to a
backtick-styled test name to match the repository style (for example: fun
`search messages with next and sort`()) by updating the function declaration in
ChatClientGeneralApiTests (the runTest block and contents remain unchanged);
ensure any direct references to searchMessagesWithNextAndSort in the test class
are updated to the new backtick name so the test runner still discovers and
executes it.
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerStateTest.kt (1)

173-305: Consider asserting no local deletion on Success-path preconditions.

A small negative verification would lock in that successful preconditions don’t accidentally trigger local deletes.

🧪 Optional test tightening
+import org.mockito.kotlin.never
@@
     fun `onMessageDeletePrecondition when message has SYNC_NEEDED should return Success`() =
         runTest {
@@
             val result = deleteMessageListenerState.onMessageDeletePrecondition(testMessage.id)

             assertTrue(result is Result.Success)
+            verify(channelLogic, never()).deleteMessage(any())
         }
@@
     fun `onMessageDeletePrecondition when message is COMPLETED regular should return Success`() = runTest {
@@
         val result = deleteMessageListenerState.onMessageDeletePrecondition(testMessage.id)

         assertTrue(result is Result.Success)
+        verify(channelLogic, never()).deleteMessage(any())
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerStateTest.kt`
around lines 173 - 305, The tests for
deleteMessageListenerState.onMessageDeletePrecondition lack negative assertions
that ensure no local deletion occurs on Success paths; update the Success-path
tests (the ones expecting Result.Success) to also verify that
channelLogic.deleteMessage and threadsLogic.deleteMessage are not called (use
verify(..., never()) or equivalent) to lock in that successful preconditions
don't trigger local deletes; reference the tests invoking
deleteMessageListenerState.onMessageDeletePrecondition and assert no
interactions with channelLogic.deleteMessage and threadsLogic.deleteMessage
where appropriate.
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt (1)

217-236: Prefer removing the ComplexCondition suppression by extracting a named predicate.

The suppression can be avoided with a small readability refactor.

♻️ Proposed refactor
-@Suppress("ComplexCondition")
 `@InternalStreamChatApi`
 public fun Message.shouldDeleteRemote(currentUserId: String?): Result<Unit> {
@@
-    if (isError() || isEphemeral() ||
-        syncStatus == SyncStatus.IN_PROGRESS ||
-        syncStatus == SyncStatus.FAILED_PERMANENTLY
-    ) {
+    val isLocalOnlyByTypeOrSyncStatus =
+        isError() || isEphemeral() || syncStatus == SyncStatus.IN_PROGRESS || syncStatus == SyncStatus.FAILED_PERMANENTLY
+
+    if (isLocalOnlyByTypeOrSyncStatus) {
         val error = Error.GenericError("Message is local-only, don't call DeleteMessage API")
         return Result.Failure(error)
     }

As per coding guidelines: "Use @OptIn annotations explicitly; avoid suppressions unless documented".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt`
around lines 217 - 236, Remove the `@Suppress`("ComplexCondition") and replace the
inline complex boolean in Message.shouldDeleteRemote with a named predicate
variable (e.g., val notPersistedRemotely or shouldDeleteLocally) that captures
isError(), isEphemeral(), syncStatus == SyncStatus.IN_PROGRESS, and syncStatus
== SyncStatus.FAILED_PERMANENTLY; then use if (notPersistedRemotely) { ... } to
preserve behavior. Keep the `@InternalStreamChatApi` annotation and existing logic
around isModerationError(...) and the Error.ThrowableError creation unchanged.
Ensure no other suppressions are added.
stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/search/SearchViewModelTest.kt (1)

178-180: Unnecessary suspend modifier on mock configuration.

The givenRepositorySelectChannels function only configures a mock with whenever(...) doReturn ...—it doesn't actually invoke the suspend function. The suspend modifier adds unnecessary complexity to the builder pattern.

♻️ Suggested fix
-        suspend fun givenRepositorySelectChannels(channels: List<Channel> = emptyList()) = apply {
+        fun givenRepositorySelectChannels(channels: List<Channel> = emptyList()) = apply {
             whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn channels
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/search/SearchViewModelTest.kt`
around lines 178 - 180, The helper function givenRepositorySelectChannels is
marked suspend unnecessarily; change its signature to a regular (non-suspending)
function so it only configures the mock without requiring a coroutine context.
Update the function declaration for givenRepositorySelectChannels(...) to remove
the suspend modifier and keep the body as-is
(whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn
channels), and adjust any test callers to no longer call it from a coroutine if
they do.
stream-chat-android-compose/api/stream-chat-android-compose.api (1)

945-945: Add explicit migration notes for the updated public signatures.

Line 945, Line 2440, Line 4119, and Line 4159 introduce signature/constructor parameter changes in public APIs. Please add precise migration entries (new params + ordering) in v7 migration/changelog docs.

Based on learnings: In GetStream/stream-chat-android v7, breaking API changes are acceptable, but migration paths should be documented in MIGRATION_TO_V7.md/CHANGELOG.

Also applies to: 2440-2440, 4119-4120, 4159-4160

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stream-chat-android-compose/api/stream-chat-android-compose.api` at line 945,
Update the v7 migration docs to document the changed public signatures
introduced (notably the ChannelsScreen composable signature shown as
ChannelsScreen(Lio/getstream/chat/android/compose/viewmodel/channels/ChannelViewModelFactory;Ljava/lang/String;Ljava/lang/String;ZLio/getstream/chat/android/compose/ui/channels/SearchMode;...
) and the other changed constructors at the same commits), by adding precise
migration notes listing each new parameter, their types, ordering,
default/nullable behavior, and example call-site before/after; add these entries
to MIGRATION_TO_V7.md and CHANGELOG (or the project's v7 migration doc) so
callers know how to update usages of ChannelsScreen and the other changed
constructors.
stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt (1)

62-69: Consider using a more idiomatic constructor pattern.

The secondary constructor that mutates a var after delegating to the primary constructor works but is unconventional. A cleaner approach would be to make the primary constructor accept both parameters with defaults.

However, this is acceptable for backward compatibility since the existing primary constructor signature must be preserved.

Alternative approach (optional)
 public class StreamImageLoaderFactory(
+    private val interceptors: List<Interceptor> = emptyList(),
     private val builder: ImageLoader.Builder.() -> Unit = {},
 ) : SingletonImageLoader.Factory {
-
-    /**
-     * Creates a [StreamImageLoaderFactory] with additional [Interceptor]s...
-     */
-    public constructor(
-        interceptors: List<Interceptor>,
-        builder: ImageLoader.Builder.() -> Unit = {},
-    ) : this(builder) {
-        this.interceptors = interceptors
-    }
-
-    private var interceptors: List<Interceptor> = emptyList()

Note: This would be a breaking change for binary compatibility, so the current approach may be intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt`
around lines 62 - 69, Change the class to accept interceptors in the primary
constructor instead of mutating a var from the secondary one: add a parameter
interceptors: List<Interceptor> = emptyList() to the primary constructor of
StreamImageLoaderFactory and initialize the property from that parameter, then
remove the secondary constructor that sets this.interceptors; update or remove
the private var interceptors declaration to be initialized from the constructor
parameter (or make it val if immutable). This preserves behavior but uses the
more idiomatic constructor pattern and keeps the existing primary constructor
body intact for backward-compatibility considerations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt`:
- Around line 64-67: Update the KDoc for the public API that determines reply
eligibility to reflect the new deleted-message precondition: document that
replies are only allowed when replyEnabled is true, the message is synced
(message.isSynced()), the message is not deleted (message.isDeleted() == false),
and the user has the QUOTE_MESSAGE capability
(ownCapabilities.contains(ChannelCapabilities.QUOTE_MESSAGE)); locate the KDoc
for the function/property that returns the Boolean (the expression using
replyEnabled, message.isSynced(), message.isDeleted(), and
ChannelCapabilities.QUOTE_MESSAGE) and add a short note about thread/state
expectations and that deleted messages are excluded from replies.

In `@stream-chat-android-ui-components/api/stream-chat-android-ui-components.api`:
- Around line 5212-5213: Update the changelog to document the public API
constructor signature change for SearchViewModel.State: add an entry under the
"⚠️ Changed" section for the stream-chat-android-ui-components component noting
that the SearchViewModel.State constructor signature was changed (list the new
parameter order/types as shown in the API: (String, Boolean, List, Boolean,
Boolean, String) and mention that a synthetic/kotlin DefaultConstructorMarker
overload was added), and include guidance for users migrating any direct uses of
the old constructor to the new parameter set.

---

Outside diff comments:
In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt`:
- Around line 1753-1757: Update the KDoc for the public function searchMessages
to match runtime validation: change the `@param` lines so offset is documented as
only incompatible with next (remove the "cannot be used with sort or next"
wording), document that sort may be used together with offset, and keep next
documented as "cannot be used with non-zero offset"; ensure the KDoc entries for
offset, limit, next, and sort reflect these exact compatibility rules and
mention any thread/state expectations present on the public searchMessages API.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt`:
- Around line 362-363: The verbose log in loadMoreQueryMessages is printing the
literal string 'query' instead of the variable value; update the logger.v call
that references currentState.query (variable name query) to interpolate or
concatenate the actual query variable (e.g., include query) so the log shows the
real query content when calling logger.v in ChannelListViewModel.

---

Nitpick comments:
In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt`:
- Around line 217-236: Remove the `@Suppress`("ComplexCondition") and replace the
inline complex boolean in Message.shouldDeleteRemote with a named predicate
variable (e.g., val notPersistedRemotely or shouldDeleteLocally) that captures
isError(), isEphemeral(), syncStatus == SyncStatus.IN_PROGRESS, and syncStatus
== SyncStatus.FAILED_PERMANENTLY; then use if (notPersistedRemotely) { ... } to
preserve behavior. Keep the `@InternalStreamChatApi` annotation and existing logic
around isModerationError(...) and the Error.ThrowableError creation unchanged.
Ensure no other suppressions are added.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientGeneralApiTests.kt`:
- Line 235: Rename the test function searchMessagesWithNextAndSort to a
backtick-styled test name to match the repository style (for example: fun
`search messages with next and sort`()) by updating the function declaration in
ChatClientGeneralApiTests (the runTest block and contents remain unchanged);
ensure any direct references to searchMessagesWithNextAndSort in the test class
are updated to the new backtick name so the test runner still discovers and
executes it.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerStateTest.kt`:
- Around line 173-305: The tests for
deleteMessageListenerState.onMessageDeletePrecondition lack negative assertions
that ensure no local deletion occurs on Success paths; update the Success-path
tests (the ones expecting Result.Success) to also verify that
channelLogic.deleteMessage and threadsLogic.deleteMessage are not called (use
verify(..., never()) or equivalent) to lock in that successful preconditions
don't trigger local deletes; reference the tests invoking
deleteMessageListenerState.onMessageDeletePrecondition and assert no
interactions with channelLogic.deleteMessage and threadsLogic.deleteMessage
where appropriate.

In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Line 945: Update the v7 migration docs to document the changed public
signatures introduced (notably the ChannelsScreen composable signature shown as
ChannelsScreen(Lio/getstream/chat/android/compose/viewmodel/channels/ChannelViewModelFactory;Ljava/lang/String;Ljava/lang/String;ZLio/getstream/chat/android/compose/ui/channels/SearchMode;...
) and the other changed constructors at the same commits), by adding precise
migration notes listing each new parameter, their types, ordering,
default/nullable behavior, and example call-site before/after; add these entries
to MIGRATION_TO_V7.md and CHANGELOG (or the project's v7 migration doc) so
callers know how to update usages of ChannelsScreen and the other changed
constructors.

In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt`:
- Around line 62-69: Change the class to accept interceptors in the primary
constructor instead of mutating a var from the secondary one: add a parameter
interceptors: List<Interceptor> = emptyList() to the primary constructor of
StreamImageLoaderFactory and initialize the property from that parameter, then
remove the secondary constructor that sets this.interceptors; update or remove
the private var interceptors declaration to be initialized from the constructor
parameter (or make it val if immutable). This preserves behavior but uses the
more idiomatic constructor pattern and keeps the existing primary constructor
body intact for backward-compatibility considerations.

In
`@stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/search/SearchViewModelTest.kt`:
- Around line 178-180: The helper function givenRepositorySelectChannels is
marked suspend unnecessarily; change its signature to a regular (non-suspending)
function so it only configures the mock without requiring a coroutine context.
Update the function declaration for givenRepositorySelectChannels(...) to remove
the suspend modifier and keep the body as-is
(whenever(repositoryFacade.selectChannels(any<List<String>>())) doReturn
channels), and adjust any test callers to no longer call it from a coroutine if
they do.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9efac234-fc72-43e5-a8e2-6f2257b70b45

📥 Commits

Reviewing files that changed from the base of the PR and between 046fb84 and 946eabe.

⛔ Files ignored due to path filters (4)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_my_message.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_my_message_in_dark_mode.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_SelectedMessageMenuTest_their_message_in_dark_mode.png is excluded by !**/*.png
📒 Files selected for processing (48)
  • .github/workflows/pr-checks.yml
  • .github/workflows/pr-cleanup.yaml
  • .github/workflows/pr-quality.yml
  • .github/workflows/publish-new-version.yml
  • .github/workflows/sdk-size-checks.yml
  • .github/workflows/sdk-size-updates.yml
  • README.md
  • build.gradle.kts
  • gradle.properties
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/offline/plugin/listener/internal/DeleteMessageListenerDatabase.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerState.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogic.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/socket/SocketFactory.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/internal/MessageUtils.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/utils/message/MessageUtils.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/ChatClientGeneralApiTests.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/offline/plugin/listener/internal/DeleteMessageListenerDatabaseTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/listener/internal/DeleteMessageListenerStateTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogicTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/socket/SocketFactoryTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/utils/internal/MessageUtilsTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/utils/message/MessageUtilsTest.kt
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/channels/ChannelsScreen.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageContainer.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/theme/ChatTheme.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/ImageHeadersInterceptor.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/StreamCoilImageLoaderFactory.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModel.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/channels/ChannelViewModelFactory.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/viewmodel/messages/AttachmentsPickerViewModel.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/util/extensions/MessageOptionItemVisibilityTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/viewmodel/channels/ChannelListViewModelTest.kt
  • stream-chat-android-ui-common/api/stream-chat-android-ui-common.api
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/helper/AsyncImageHeadersProvider.kt
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/images/StreamImageLoaderFactory.kt
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt
  • stream-chat-android-ui-common/src/main/res/xml/stream_filepaths.xml
  • stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelperTest.kt
  • stream-chat-android-ui-components/api/stream-chat-android-ui-components.api
  • stream-chat-android-ui-components/detekt-baseline.xml
  • stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt
  • stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/feature/messages/list/internal/MessageListViewExtensionsKtTest.kt
  • stream-chat-android-ui-components/src/test/kotlin/io/getstream/chat/android/ui/viewmodels/search/SearchViewModelTest.kt
💤 Files with no reviewable changes (2)
  • stream-chat-android-ui-components/detekt-baseline.xml
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/utils/internal/MessageUtilsTest.kt

Comment on lines +64 to +67
): Boolean = replyEnabled &&
message.isSynced() &&
!message.isDeleted() &&
ownCapabilities.contains(ChannelCapabilities.QUOTE_MESSAGE)
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 | 🟡 Minor

KDoc is missing the new deleted-message precondition.

Line [66] now blocks replies for deleted messages, but the KDoc still lists only sync/capability/UI-flag conditions.

📝 Suggested KDoc patch
  * A reply is allowed when:
  * - Reply functionality is enabled in the UI configuration
  * - The message has been successfully synced with the backend
+ * - The message is not deleted
  * - The user has the capability to quote messages in the channel

As per coding guidelines **/*.kt: "Document public APIs with KDoc, including thread expectations and state notes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/utils/CapabilitiesHelper.kt`
around lines 64 - 67, Update the KDoc for the public API that determines reply
eligibility to reflect the new deleted-message precondition: document that
replies are only allowed when replyEnabled is true, the message is synced
(message.isSynced()), the message is not deleted (message.isDeleted() == false),
and the user has the QUOTE_MESSAGE capability
(ownCapabilities.contains(ChannelCapabilities.QUOTE_MESSAGE)); locate the KDoc
for the function/property that returns the Boolean (the expression using
replyEnabled, message.isSynced(), message.isDeleted(), and
ChannelCapabilities.QUOTE_MESSAGE) and add a short note about thread/state
expectations and that deleted messages are excluded from replies.

Comment on lines +5212 to +5213
public fun <init> (Ljava/lang/String;ZLjava/util/List;ZZLjava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ZLjava/util/List;ZZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
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
set -euo pipefail

echo "Looking for migration/changelog files..."
docs="$(fd -HI '^(MIGRATION_TO_V7\.md|CHANGELOG(\.md)?)$' || true)"

if [ -z "${docs}" ]; then
  echo "No MIGRATION_TO_V7.md/CHANGELOG(.md) files found."
  exit 0
fi

echo "Scanning docs for SearchViewModel/State API change mentions..."
while IFS= read -r f; do
  echo "----- ${f} -----"
  rg -n "SearchViewModel|SearchViewModel\\$State|search state|cursor|pagination|messageSearchSort" "${f}" || true
done <<< "${docs}"

Repository: GetStream/stream-chat-android

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking for migration and changelog files ==="
fd -HI '^(MIGRATION_TO_V7\.md|MIGRATION\.md|CHANGELOG\.md)$' 2>/dev/null || echo "No files found"

echo ""
echo "=== Examining the API file around lines 5212-5213 and 5219-5220 ==="
if [ -f "stream-chat-android-ui-components/api/stream-chat-android-ui-components.api" ]; then
  echo "Lines 5210-5225:"
  sed -n '5210,5225p' "stream-chat-android-ui-components/api/stream-chat-android-ui-components.api" | cat -n
fi

echo ""
echo "=== Searching CHANGELOG for SearchViewModel mentions ==="
if [ -f "CHANGELOG.md" ]; then
  rg -A 3 -B 1 "SearchViewModel" CHANGELOG.md || echo "No SearchViewModel mentions found in CHANGELOG"
fi

echo ""
echo "=== Checking for MIGRATION_TO_V7.md ==="
if [ -f "MIGRATION_TO_V7.md" ]; then
  echo "File exists. Searching for SearchViewModel or State changes..."
  rg -A 3 -B 1 "SearchViewModel|State|cursor|pagination|messageSearchSort" MIGRATION_TO_V7.md || echo "No relevant mentions found"
else
  echo "MIGRATION_TO_V7.md not found"
fi

Repository: GetStream/stream-chat-android

Length of output: 1637


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking git branch ==="
git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "Unable to determine branch"

echo ""
echo "=== Looking for migration or documentation files in the PR ==="
fd -HI 'MIGRATION|migration' -t f 2>/dev/null | head -20

echo ""
echo "=== Checking recent CHANGELOG entries for any v7 migration context ==="
if [ -f "CHANGELOG.md" ]; then
  head -50 CHANGELOG.md | cat -n
fi

echo ""
echo "=== Searching for SearchViewModel in source code to understand the change ==="
fd -t f -e kt -e java 'SearchViewModel' | head -5 | while read f; do
  echo "--- Found: $f ---"
  grep -n "constructor\|fun State\|class State" "$f" 2>/dev/null | head -10 || true
done

Repository: GetStream/stream-chat-android

Length of output: 2164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Reading SearchViewModel.kt State class definition ==="
if [ -f "stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt" ]; then
  wc -l "stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt"
  echo ""
  sed -n '190,230p' "stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/viewmodel/search/SearchViewModel.kt" | cat -n
fi

echo ""
echo "=== Checking git diff to see what changed in API ==="
git diff HEAD~1 stream-chat-android-ui-components/api/stream-chat-android-ui-components.api 2>/dev/null | head -100 || echo "Unable to get git diff"

echo ""
echo "=== Checking if this is a major version branch ==="
git branch -a 2>/dev/null | grep -i "v7\|main\|develop" || echo "Unable to determine branches"

Repository: GetStream/stream-chat-android

Length of output: 1391


Document this public API signature change in CHANGELOG.md.

The SearchViewModel.State constructor signature change is not documented. Add an entry to the "⚠️ Changed" section of the stream-chat-android-ui-components component in CHANGELOG.md describing the parameter modifications to State so users upgrading have clear visibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stream-chat-android-ui-components/api/stream-chat-android-ui-components.api`
around lines 5212 - 5213, Update the changelog to document the public API
constructor signature change for SearchViewModel.State: add an entry under the
"⚠️ Changed" section for the stream-chat-android-ui-components component noting
that the SearchViewModel.State constructor signature was changed (list the new
parameter order/types as shown in the API: (String, Boolean, List, Boolean,
Boolean, String) and mention that a synthetic/kotlin DefaultConstructorMarker
overload was added), and include guidance for users migrating any direct uses of
the old constructor to the new parameter set.

Copy link
Copy Markdown
Contributor

@gpunto gpunto left a comment

Choose a reason for hiding this comment

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

No concerns on my side

# Conflicts:
#	stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt
# Conflicts:
#	stream-chat-android-compose/api/stream-chat-android-compose.api
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
73.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@VelikovPetar VelikovPetar merged commit 54cb625 into v7 Mar 18, 2026
18 of 20 checks passed
@VelikovPetar VelikovPetar deleted the merge/develop_to_v7_20260317 branch March 18, 2026 09:35
@stream-public-bot stream-public-bot added the released Included in a release label Mar 23, 2026
@stream-public-bot
Copy link
Copy Markdown
Contributor

🚀 Available in v7.0.0-beta

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

Labels

pr:internal Internal changes / housekeeping released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants