Skip to content

Mobile: thread-reply edits are live-only and revert after reopen because history omits include_aux #7058

Description

@futpib

Summary

Buzz Mobile applies a kind 40003 edit to a thread reply when the edit arrives through the live channel subscription. If Mobile misses that live event, or refetches the thread after reconnecting or reopening it, the reply renders its original pre-edit content.

Top-level message edits survive reload because the channel-window request uses include_aux: true. Historical thread-reply requests do not.

Confirmed by source inspection on current main at eed74bde2.

Steps to reproduce

  1. Post a reply inside a channel thread.
  2. Disconnect, background, or stop the Android client.
  3. Edit that reply from another client.
  4. Confirm the relay contains both the original reply and its kind 40003 edit.
  5. Reconnect Android and reopen the thread.

Actual: Mobile shows the original reply.

Control: if Android remains connected while the edit is published, the updated content may appear live. A later refetch can replace that live state with the original content.

Expected behavior

A cold thread load, reopen, or reconnect should apply the latest valid edit and show the (edited) label, exactly as the live path does.

Root cause

mobile/lib/features/channels/thread_replies_provider.dart::_threadRepliesFilter() requests only EventKind.channelTimelineContentKinds:

extensions: {
  'depth_limit': 64,
  if (cursor != null) 'thread_cursor': cursor.createdAt,
  if (cursor != null) 'thread_cursor_id': cursor.eventId,
},

It does not request include_aux.

The relay already supports include_aux on thread queries and returns the auxiliary closure for the root and fetched replies, including edits, reactions, and deletions. formatTimeline() already applies kind 40003 correctly when the edit is present in its event array.

The main channel-window request uses include_aux: true, but that closure targets the returned top-level rows; it does not backfill edits for replies loaded separately by the thread query.

This is the mobile equivalent of the desktop bug fixed in #1610. That PR explicitly identified the server-side thread include_aux path as the follow-up that would fix mobile clients. The relay path now exists; Mobile does not request it.

Fix boundary

Add include_aux: true to the historical thread filter.

Because auxiliary events are appended to the response, pagination must count and choose its cursor from content reply events—not events.length or events.last. Otherwise a page containing auxiliary events can falsely appear full or use an edit/reaction as the next reply cursor.

Regression coverage

Extend mobile/test/features/channels/thread_replies_provider_test.dart to verify:

  • thread queries send include_aux: true;
  • a cold load containing a reply plus its edit renders the edited body;
  • reconnect/refetch does not revert a live edit;
  • the latest valid edit wins;
  • pagination derives exhaustion and the next cursor from content replies when auxiliary events are also returned.

Version and platform

  • Buzz Mobile: current upstream source at eed74bde2
  • Platform: Android
  • Relay: self-hosted, with the kind 40003 edit confirmed stored

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions