Fix link preview resolution and skipEnrichUrl in message composer#6363
Fix link preview resolution and skipEnrichUrl in message composer#6363
Conversation
TestCoroutineExtension already overrides DispatcherProvider for deterministic tests but was missing the equivalent CallDispatcherProvider setup. This caused Call.await() (via MapCall) to hop to real Dispatchers.IO, making tests non-deterministic.
…reventing a resolved preview from appearing in an already-cleared composer after send. - Replace skipEnrichUrl derivation from linkPreviews.isEmpty() with intent-based logic aligned with the iOS SDK: default to false (let backend enrich), only skip when the user explicitly dismisses the preview or the text contains no URLs. Integrator overrides from ChannelScreen are preserved.
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
WalkthroughThe PR changes link-preview handling from a list to a single nullable preview, adds dismissal tracking and coroutine job lifecycle for preview enrichment, updates UI and state APIs accordingly, adjusts message sending to respect a new skip-enrichment decision, and configures call dispatchers in test setup/reset. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as MessageInput UI
participant Controller as MessageComposerController
participant Enricher as LinkPreviewEnricher
participant Sender as MessageSender
User->>UI: Type text with URL
UI->>Controller: onInputChanged(debounced)
Controller->>Enricher: start enrichUrl(url) (async) (linkPreviewJob)
Enricher-->>Controller: enrich result (may be late)
alt user cancels/dismisses before enrich completes
User->>UI: dismiss/cancel preview
UI->>Controller: cancelLinkPreview()
Controller->>Controller: record dismissedLinkPreviewUrl, cancel linkPreviewJob, set linkPreview=null
Enricher-->>Controller: (late) result ignored
end
User->>UI: hit send
UI->>Controller: sendMessage()
Controller->>Controller: shouldSkipEnrichUrl(message) -> true/false
Controller->>Sender: send(message with skipEnrichUrl flag)
Sender-->>Controller: ack
Controller-->>UI: update state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsTimed out fetching pipeline failures after 30000ms 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. Comment |
...n/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt
Outdated
Show resolved
Hide resolved
…e called Then skipEnrichUrl is true
…ead of a list as per iOS.
...n/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt
Outdated
Show resolved
Hide resolved
...n/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.kt
Show resolved
Hide resolved
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
stream-chat-android-ui-common/api/stream-chat-android-ui-common.api (1)
2293-2305: Please make sure thisMessageComposerStatepublic API break is called out in migration notes.This surface now exposes a single
LinkPreviewacross constructors,component7,copy, and the getter, so SDK consumers using the old list-based model will need an explicit upgrade note.Based on learnings: in major version branches like v7, breaking public API changes are allowed, but maintainers prefer documenting migration paths in
MIGRATION_TO_V7.md/CHANGELOG.Also applies to: 2321-2325, 2336-2336
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@stream-chat-android-ui-common/api/stream-chat-android-ui-common.api` around lines 2293 - 2305, Public API for MessageComposerState changed from exposing a list of LinkPreview to a single LinkPreview across its constructors, component7, copy, and getter; add a clear migration note in MIGRATION_TO_V7.md and CHANGELOG calling out MessageComposerState (all its constructors and the synthetic constructor), component7, copy, and the getter, explaining the type change (List<LinkPreview> -> LinkPreview) and providing a short migration example (how to pick/convert the old List<LinkPreview> to a single LinkPreview, e.g., firstOrNull or map to a single preview) plus any recommended runtime checks; ensure the note references the exact symbol MessageComposerState and mentions the affected methods so consumers can find and update usages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@stream-chat-android-ui-common/api/stream-chat-android-ui-common.api`:
- Around line 2293-2305: Public API for MessageComposerState changed from
exposing a list of LinkPreview to a single LinkPreview across its constructors,
component7, copy, and getter; add a clear migration note in MIGRATION_TO_V7.md
and CHANGELOG calling out MessageComposerState (all its constructors and the
synthetic constructor), component7, copy, and the getter, explaining the type
change (List<LinkPreview> -> LinkPreview) and providing a short migration
example (how to pick/convert the old List<LinkPreview> to a single LinkPreview,
e.g., firstOrNull or map to a single preview) plus any recommended runtime
checks; ensure the note references the exact symbol MessageComposerState and
mentions the affected methods so consumers can find and update usages.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3cfbecde-78bc-4eb3-9190-0c9c6a76249d
📒 Files selected for processing (6)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/composer/MessageInput.ktstream-chat-android-docs/src/main/java/io/getstream/chat/docs/java/ui/guides/ImplementingOwnCapabilities.javastream-chat-android-ui-common/api/stream-chat-android-ui-common.apistream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerController.ktstream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/state/messages/composer/MessageComposerState.ktstream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/feature/messages/composer/MessageComposerControllerTest.kt



Goal
Fix two issues with link preview resolution in the message composer:
skipEnrichUrlwas derived fromlinkPreviews.isEmpty(), conflating "preview hasn't resolved yet" with "no preview wanted." This told the backend to skip enrichment when the user simply sent before the preview loaded, resulting in no link preview on the message.Both fixes align the Android SDK with the iOS SDK's behavior.
Implementation
TestCoroutineExtensionCallDispatcherProvider.set/resetalongside the existingDispatcherProvidersetup. This was a missing counterpart —Call.await()(viaMapCall) was hopping to realDispatchers.IOin tests.MessageComposerControllerlinkPreviewJoband cancel it in both the debounce site (prevents duplicate in-flight calls) andclearData()(prevents ghost preview after send).skipEnrichUrl = linkPreviews.isEmpty()derivation with an intent-based approach: alinkPreviewDismissedflag is set only when the user taps the dismiss button (cancelLinkPreview), and reset on any text change (setMessageInputInternal). At send time,shouldSkipEnrichUrl()combines the integrator override (message.skipEnrichUrlfromChannelScreen), user dismissal, and URL presence in the text.shouldSkipEnrichUrl()to both the new-message and edit-message paths.setMessageInputby delegating tosetMessageInputInternal.MessageComposerControllerTestclearData.skipEnrichUrlisfalsewhen sending before the preview resolves (backend should enrich).skipEnrichUrlistrueafter explicit preview dismissal.No UI changes.
Testing
www.meta.com), wait for the link preview to appear, then tap Send before the preview shows — verify the sent message has a link preview (backend enriched it).Summary by CodeRabbit