Skip to content

Improve Android responsiveness and message delivery reliability - #225

Closed
Xare123 wants to merge 33 commits into
OpenBubbles:rustpushfrom
Xare123:agent/improve-app-responsiveness
Closed

Improve Android responsiveness and message delivery reliability#225
Xare123 wants to merge 33 commits into
OpenBubbles:rustpushfrom
Xare123:agent/improve-app-responsiveness

Conversation

@Xare123

@Xare123 Xare123 commented Jul 25, 2026

Copy link
Copy Markdown

All done was because my wife agreed to let me switch to android if she didn't lose the blue texts. Found the application not snappy on the Pixel 10 Pro as I hoped at first. Changes done has brought the application to life for me, hope they do for all.

Summary

This branch improves Android responsiveness and message-delivery reliability, while hardening group-chat, reply-thread, and profile/contact handling.

  • Removes avoidable UI and animation lifecycle leaks, including deferred subscription races and ticker disposal hazards.
  • Fixes message controllers being remounted after their row was recycled, which was the source of the gray placeholder blocks in long transcripts.
  • Loads complete reply threads including the originating message, so a threaded reply opens with its context instead of a single orphaned bubble.
  • Makes keyboard dismissal in a conversation reliable via Back, transcript tap, and downward swipe, and closes a leaked keyboard-visibility subscription.
  • Reduces eager full-resolution image work and background churn during contact/profile hydration.
  • Preserves incoming-message persistence and acknowledgement ordering, with serialized queue handling and safer reconnect/backoff behavior.
  • Hardens group-participant, reaction, message-update, and transcript-refresh handling.
  • Isolates malformed shared-profile payloads from message delivery, bounds retry diagnostics, and keeps render diagnostics free of message/contact content.
  • Adds Android development, diagnostics, and delivery/performance verification documentation.
  • Uses the official OpenBubbles RustPush and nested submodule URLs. The provisioning dependency chain is covered by OpenBubbles/apple-private-apis#6 and OpenBubbles/rustpush#33.

Behavior before and after

These are mechanism-level changes, each verifiable from the diff. They are described as behavior, not as benchmarked speedups.

Area Before After
Incoming queue queue() started a second processor whenever items.isEmpty && item is IncomingItem, so two runners could interleave on a burst of incoming messages A single _runnerActive guard owns the drain loop; prepItem failures complete the item's completer with the error instead of stranding it
Push acknowledgement An incoming push could be acknowledged even when the handler had already failed, permanently dropping that message The message is persisted before acknowledgement, and a failed handler does not acknowledge
Recycled message rows updateObx was a late final callback re-initialized when a widget was recycled, throwing LateError and rendering a gray error block instead of the message Controller state is torn down on recycle and re-initialized cleanly on remount; covered by a mount/dispose/remount regression test
Reply threads The thread view opened from the current 50-message window and omitted the originating message, so a reply appeared without context The full locally stored chain is loaded including the originator, in chronological order, with group sender names preserved and lazy rendering for long chains
Reconnect Socket.IO automatic reconnect and the manual reconnect path could both be in flight, causing overlapping connection attempts Reconnect is single-owner, guarded by an epoch and connection generation, so stale attempts are discarded
Keyboard Dismissing the keyboard in a conversation required Back, and a keyboard-visibility subscription was never cancelled Back, transcript tap, and downward swipe all dismiss; the subscription is cancelled on dispose

Validation

  • Focused helper, queue, and lifecycle suite: 15/15 tests passed locally, including new regression tests for controller remount and reply-thread assembly.
  • Targeted Dart analysis: no analyzer errors in the changed lifecycle, animation, message-view, header/tile, service, and diagnostics paths. Existing deprecation and unused-code warnings outside this change remain.
  • CI for the current head 6028e16: run 30159127049, building Alpha Profile and Debug APKs against the upstream-ready dependency chain.
  • The Alpha Profile artifact was signed and installed in place on a Pixel 10 Pro. A device log captured before this fix showed a repeating cascade of LateError render failures while scrolling a long transcript; the same device and same build type after the fix produced zero LateError, zero queue failures, and zero reconnect failures during startup and transcript scroll.
  • User-driven confirmation on the same Pixel, exercising the workflow that previously failed: scrolling a long group transcript, opening threaded replies, and dismissing the keyboard. Over a continuous ~14 minute session the app rendered 1,788 frames with 10 janky frames (0.56%), p50 5 ms, p95 6 ms, p99 12 ms, with no process restart and no error-level log entries from the app process. The reply thread opened with its originating message and group sender names intact.

Measurements, and their limits

The following were measured on the branch build only. There is no matching profile-mode build of the base branch, so these are single-arm observations and should not be read as a measured speedup:

  • Five cold starts on a Pixel 10 Pro: 1,272 ms, 1,303 ms, 1,201 ms, 1,108 ms, 1,301 ms (1,237 ms average).
  • SurfaceFlinger capture at 120 Hz: median frame interval 8.34 ms, p95 8.59 ms, no interval over 16.7 ms.

An earlier comparison against the Play Store release is deliberately not quoted here, because it compared a Flutter debug build to a release build and is not a valid control.

Known gaps

  • One nonfatal Rust SetLoggerError is logged during startup; initialization still completes and the app remains active.
  • Long-duration locked-phone and network-change endurance testing remains follow-up validation for maintainers.
  • No controlled A/B benchmark of base vs. branch in profile mode has been run. Happy to produce one if a maintainer wants numbers attached to the responsiveness claim.

Scope

This PR does not change the Apple validation protocol or claim support for unsupported iOS/macOS configurations. It is intended to be reviewed alongside the two dependency PRs above.

Xare123 added 30 commits July 23, 2026 21:46
@Xare123

Xare123 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Closing this in favor of three focused PRs. This one had grown to 72 files across seven unrelated themes, which is more than anyone should be asked to review in one pass.

Split into:

Each is independent, does not touch the rustpush submodule pointer, passes its own tests, and adds no analyzer errors. They share a few files but edit different regions; whichever merges first, I will rebase the others.

Four things from this PR are deliberately not in the split, because they did not belong under a responsiveness and delivery title:

  • iPhone relay health monitoring, which is a feature rather than a fix
  • The docs/DEVELOPMENT.md, docs/DIAGNOSTICS.md, and docs/VERIFICATION.md additions
  • Android control accessibility improvements
  • CI workflow changes that built profile APKs for my own device testing

All four are still on my fork and I am happy to open any of them separately if they are wanted. Just say which.

@Xare123 Xare123 closed this Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant