Skip to content

Parse the draft message with the generated model and restore the draft command round trip - #6718

Merged
gpunto merged 2 commits into
developfrom
migrate/draft-payload
Sep 23, 2026
Merged

gpunto merged 2 commits into
developfrom
migrate/draft-payload

Conversation

@gpunto

@gpunto gpunto commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Goal

Parse the draft message with the generated DraftPayloadResponse, retiring DownstreamDraftMessageDto,
and fix the two things the swap exposed: draft custom data was never read, and the active slash command
stopped being sent.

Closes AND-1473
Closes AND-1558

Part of AND-1291

Implementation

  • Point DownstreamDraftDto.message at the generated model and delete the hand-written one. Vendors
    DraftPayloadResponse, the only new model in the closure.
  • Register a collecting adapter for it, so the custom fields the wire flattens to the root land in custom.
  • Carry command and args in custom in both directions: into the request body when mapping
    DraftMessage, and back out to the typed domain fields when reading, filtered out of extraData so they
    do not show up twice.

Notes

Drafts have no dedicated command fields on the backend. Neither DraftPayloadResponse nor MessageRequest
declares them, and both carry Custom jsonextra.ExtraFields, which sweeps unknown root keys in and
flattens them back out. That is what the round trip has always relied on: UpstreamMessageDto declared
command and args, so they serialized at the root, the backend stored them as custom data, and the
response flattened them back where the typed DTO field read them.

Building the outgoing body with MessageRequest removed the two declarations and left the values nowhere
to go, so they have not been sent since v7.11.0. iOS carries the same mechanism explicitly, putting both
into custom data in asDraftMessageRequest() and reading them back in DraftPayload+Extensions, so this
matches it rather than inventing a shape.

Custom data on drafts is a separate, older bug: DownstreamDraftMessageDto declared a field literally named
extraData with no collecting adapter registered, and the wire has no key by that name, so every draft read
back with an empty map. The generated model declares custom, and registering the adapter is what makes it
arrive.

Drafts written by this SDK since v7.11.0 have no command or args in their stored custom data and cannot be
recovered. Drafts written by iOS, or by Android before that, resolve again once this lands.

Testing

Mutation sweep over DownstreamDraftDto.toDomain: zero survivors across all twelve fields.

Added a parsing test feeding root-level custom keys as JSON, a serialization test asserting both keys reach
the root of the request body, and mapper tests for the promotion and for a draft with no active command. The
draft.updated fixture now carries custom data too, so the event path is covered as well as the HTTP one.

Device-probed createDraftMessage and queryDrafts, with and without an active command. The request body
carried probe_flair, command and args flattened to the root, and both reads returned command=giphy,
args=cat and extraData={probe_flair=gold} with no command keys left in the map. The no-command pass
returned nulls and a clean map.

Summary by CodeRabbit

  • New Features

    • Draft messages now preserve command and argument data when sent and received.
    • Additional custom draft fields are retained without being confused with standard message properties.
    • Draft payloads now support consistent handling of optional attachments, mentions, visibility, and silent settings.
  • Bug Fixes

    • Drafts without command data now correctly map without empty command or argument values.
    • Improved parsing of custom fields in draft event payloads.

@gpunto gpunto added the pr:bug Bug fix label Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@gpunto
gpunto marked this pull request as ready for review September 22, 2026 16:27
@gpunto
gpunto requested a review from a team as a code owner September 22, 2026 16:27
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 36dffa18-3a09-4542-ad67-feef63a294d3

📥 Commits

Reviewing files that changed from the base of the PR and between e0cf35b and 788ca4d.

📒 Files selected for processing (13)
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.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/api2/model/dto/MessageDtos.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/DraftPayloadResponseAdapter.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/DraftPayloadResponse.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.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/parser/EventArguments.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DraftPayloadResponseAdapterTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/MessageRequestAdapterTest.kt

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


Walkthrough

Draft payloads now use a shared response model with custom-data parsing. Draft command and argument values map between custom data, domain models, and request models. Tests cover parsing, mapping, serialization, and missing command data.

Changes

Draft payload mapping

Layer / File(s) Summary
Payload contract and parsing
stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/DraftPayloadResponse.kt, stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/*, stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/MessageDtos.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/*
Introduces DraftPayloadResponse, replaces DownstreamDraftMessageDto, and registers a read-only adapter that collects flattened fields into custom.
Draft domain and request mapping
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/*, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/*, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/MessageRequestAdapterTest.kt
Maps command and arguments through custom data, excludes them from extraData, applies nullable defaults, and verifies request serialization and missing-command behavior.

Priority: ➖ Normal

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant DraftJSON
  participant MoshiChatParser
  participant DraftPayloadResponseAdapter
  participant DomainMapping
  participant DtoMapping
  DraftJSON->>MoshiChatParser: parse draft payload
  MoshiChatParser->>DraftPayloadResponseAdapter: read flattened custom fields
  DraftPayloadResponseAdapter-->>DomainMapping: return DraftPayloadResponse
  DomainMapping-->>DomainMapping: map command, args, and extraData
  DtoMapping->>DtoMapping: add non-null command data to custom
Loading

Suggested reviewers: velikovpetar

Merge Risk: ⚪ Minimal · up to 788ca

The SDK now preserves draft custom data and restores command round trips; the change is mergeable with normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.55% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 13 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the generated-model parsing change and the restoration of the draft command round trip.
Description check ✅ Passed The description is complete and directly aligned with the pull request. It includes the goal, implementation details, issue links, compatibility notes, and extensive testing information. The UI, check…
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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

I hop through fields where draft keys gleam
I tuck command and args in the stream
Custom leaves a tidy trail
Missing keys become null without fail
Moshi hums a parsing tune
The rabbit cheers beneath the moon

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

@github-actions

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 6.07 MB 6.08 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.39 MB 11.39 MB 0.00 MB 🟢
stream-chat-android-compose 13.05 MB 13.06 MB 0.00 MB 🟢

@sonarqubecloud

Copy link
Copy Markdown

@gpunto
gpunto added this pull request to the merge queue Sep 23, 2026
Merged via the queue into develop with commit a6e78c5 Sep 23, 2026
20 checks passed
@gpunto
gpunto deleted the migrate/draft-payload branch September 23, 2026 12:03
@stream-public-bot stream-public-bot added the released Included in a release label Sep 24, 2026
@stream-public-bot

Copy link
Copy Markdown
Contributor

🚀 Available in v7.12.0

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

Labels

pr:bug Bug fix released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants