Files
buzz/mobile/lib
Tom Brow 7b9551aba8 fix(ios): open push replies in their containing thread (#8294)
Tapping a push notification for a thread reply currently opens the
channel at its parent. Preserve the verified event's direct-parent
thread ID through the iOS notification payload and Flutter bridge so the
tap opens the containing thread and highlights that exact reply, even
when newer replies have arrived. This matches Inbox's destination
selection for nested replies; broadcast replies still open in the
channel.

Closest related work: https://github.com/block/buzz/pull/6159 (original
push-tap routing).

### Validation

- Follow-up
[5b70e1a](5b70e1a5cb)
selects the last valid 64-character ASCII-hex reply marker, matching
relay ingest. Regression tests failed before the fix; all 80 XCTest and
47 Swift Testing tests passed afterward with Xcode 26.5. [Current-head
CI](https://github.com/block/buzz/actions/runs/38607128406) passed,
including Flutter tests, Android build, native package tests, complete
iOS simulator and unsigned release builds, and native accessibility
tests. The [current-head security
review](https://github.com/block/buzz/pull/8294#issuecomment-6174205374)
reports no findings. Physical evidence below predates this
validation-only follow-up.

- [Baseline CI on
f465f91](https://github.com/block/buzz/actions/runs/38436936153) passed,
including Flutter and native package tests, Android build, complete iOS
simulator and unsigned release builds, and native accessibility tests.
- Full local validation passed on
[f465f91](f465f9196f),
including 3,215 Flutter tests (four skipped) and three unconfigured-push
tests. The 49 focused navigation tests also passed after the baseline
merge.
- Added coverage for cold/warm bridge delivery, exact reply highlighting
with newer arrivals, direct-parent and broadcast destinations, and
malformed optional thread IDs. The Codex finding for an empty reply
marker is fixed and resolved.
- Physical acceptance passed on the managed iPhone 12 mini using signed
Buzz Dev 10140, built from f465f91 with SDK 26.5. Real push taps and
Inbox opened the same containing thread and highlighted the exact reply.
An older alert retained its target after a newer reply arrived; a
retained alert also worked after terminating the app. Top-level push
navigation reached the channel.
- Installed in place with the existing identity, app data and pairing
retained. No key reset or rotation was performed. Notifications were
restored to off and device control released. Xcode 27 hits an unchanged
dependency compiler error; the matching Xcode 26.5 toolchain built and
signed this tested candidate successfully.

### Physical acceptance

| Warm push: older reply A | Inbox: reply B | Cold push: reply B |
| --- | --- | --- |
| ![Older reply A highlighted with newer B
visible](https://raw.githubusercontent.com/block/buzz/87eb00d209cf0b0dd3f4146e3219b15884133b9d/pr-8294--warm-older-reply.png)
| ![Inbox highlights reply
B](https://raw.githubusercontent.com/block/buzz/87eb00d209cf0b0dd3f4146e3219b15884133b9d/pr-8294--inbox-exact-reply.png)
| ![Cold push highlights reply
B](https://raw.githubusercontent.com/block/buzz/87eb00d209cf0b0dd3f4146e3219b15884133b9d/pr-8294--cold-push-exact-reply.png)
|

[Physical test
details](https://github.com/block/buzz/pull/8294#issuecomment-6151991840).

### Before and after

Synthetic Flutter widget captures with a newer reply already present.

| Before: channel at outer parent | After: exact reply in containing
thread |
| --- | --- |
|
![Before](https://raw.githubusercontent.com/block/buzz/d9a0ff6c7a5ea481b04cb9c61d301553b4c23c10/pr-8294--before.png)
|
![After](https://raw.githubusercontent.com/block/buzz/d9a0ff6c7a5ea481b04cb9c61d301553b4c23c10/pr-8294--after.png)
|

After merge, repeat warm/cold push versus Inbox in the integrated mobile
candidate, including older alerts, top-level and broadcast
notifications.

---------

Signed-off-by: Tom Brow <tomb@block.xyz>
2026-10-14 12:35:58 -07:00
..