Skip to content

fix(mobile): keep iOS message menu actions responsive after rebuilds - #7758

Merged
brow merged 1 commit into
mainfrom
fix-mobile-menu-taps
Sep 19, 2026
Merged

brow merged 1 commit into
mainfrom
fix-mobile-menu-taps

Conversation

@brow

@brow brow commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Long-pressing a message while the keyboard dismissed could leave the iOS action menu visible but unresponsive. Rebuilds installed a new selection handler before the previous hook's cleanup removed it. Keep that handler for the native view's lifetime and dispatch to the latest callback. Also let taps on decorative action icons reach the row control.

Added regression coverage for callback rebuilds, view replacement/dismissal, and native icon/label/edge hit targets. The callback regression fails before the fix and passes after it.

Validation: all 2,257 mobile tests (4 skipped), three unconfigured-push tests, mobile analysis, 42 focused action/handler tests, and three native XCTest checks passed. Physical iOS 26.5 taps verified keyboard-open long press, Edit, Copy (including clipboard contents), repeated opening, and outside dismissal. Desktop tests/builds, Tauri checks/tests, and the web build passed. The full local gate encountered unrelated Rust agent timeout failures; all 105 tests in the affected ACP test module passed when rerun serially.

GitHub CI passed, including mobile tests, Swift tests, Android build, and iOS simulator/release builds. Codex code review completed without findings.

No matching open issue or PR found.

Before

Synthetic message using the production long-press/menu components: Edit and Copy taps leave the menu open; tapping outside still dismisses it.

buzz-menu-before.mp4

After

With the keyboard open, the first Edit icon tap opens the editor. Reopening and tapping Copy copies the message and dismisses the menu.

buzz-menu-after.mp4

@github-actions

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 5511b56fcf0047f9d0d4887dc75125b6933a6bbd...a49b21f6ddf3c6a0403a3bb692daeabccb6d4bad.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review a49b21f6ddf3c6a0403a3bb692daeabccb6d4bad to authorize a new review.
Any previous review applies only to its recorded range.

@brow

brow commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@brow

brow commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

@builderbot review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-19T17:16:45.706168Z a49b21f Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@brow

brow commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

@buzz-security-review a49b21f

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: a49b21f6dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@brow
brow marked this pull request as ready for review September 19, 2026 17:13
@brow
brow requested a review from a team as a code owner September 19, 2026 17:14
@brow
brow enabled auto-merge (squash) September 19, 2026 17:20

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:bot: Jude’s code review agent

Verdict: APPROVE
Reviewed: 5511b56fcf0047f9d0d4887dc75125b6933a6bbd..a49b21f6ddf3c6a0403a3bb692daeabccb6d4bad (exact live head a49b21f6ddf3c6a0403a3bb692daeabccb6d4bad)
Risk: medium — user-visible iOS input handling across Flutter hook lifecycle and a native platform-view method channel.

Behavior/contracts traced: The per-view method channel is now owned by stable viewId, while a ref dispatches selections to the latest rebuild callback. View replacement and dismissal clear the appropriate handler; late old-view calls have no Dart handler; the existing one-shot selection guard prevents duplicate effects. Native action rows remain the sole accessible button, while decorative icon content no longer intercepts row taps.

Findings: No blocking or non-blocking code defect. The focused Dart regression is causally bound: restoring callback identity to the effect key fails the rebuild case by losing frame4:edit. Independent native mutation evidence likewise shows restoring icon interception fails the whole-row hit-target XCTest.

Author action: none.
Verification owner: CI/release gate for broader RunnerTests.xctest coverage and optional physical-device/VoiceOver dogfood; reviewer/tooling for any additional semantic traversal capture.

Validation at matching clean HEAD:

  • just mobile-test — PASS: 2,257 tests, 4 skipped; unconfigured-push follow-up 3/3 PASS.
  • just mobile-check — PASS: 577 files formatted, 0 changed; analyzer clean.
  • cd mobile && flutter test test/features/channels/native_message_action_selection_test.dart — PASS 2/2.
  • Causal mutation restoring [viewId, onSelected] — expected FAIL: rebuild test lost the second selection; candidate restored cleanly.
  • Independent focused native XCTest and inverse hit-target mutation — PASS/expected FAIL on iPhone 17 Pro simulator, iOS 26.5.
  • Exact-head GitHub Mobile, Mobile Swift, DCO, Semgrep, and zizmor gates — PASS.

Manual/native evidence: The attached before/after recordings show the failure and the repaired keyboard-open long-press → Edit → reopen → Copy → reopen → outside-dismiss journey. Independent simulator proof covered icon, label, and row-edge targets. Physical-device execution and clipboard contents were not independently repeated in this review.

Residual risk: Low. Repository CI builds the iOS simulator/release app but does not run the full RunnerTests.xctest suite; physical-device and VoiceOver traversal remain release/dogfood confidence gaps, not author-actionable defects.

@brow
brow merged commit 4ee9f8b into main Sep 19, 2026
49 checks passed
@brow
brow deleted the fix-mobile-menu-taps branch September 19, 2026 17:25

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review verdict: APPROVE

Reviewed base 5511b56fcf0047f9d0d4887dc75125b6933a6bbd → exact live head a49b21f6ddf3c6a0403a3bb692daeabccb6d4bad.

No unresolved author-actionable defects found. Author action: none.

The fix puts selection-handler ownership on the native view identity rather than rebuild callback identity: useEffect(..., [viewId]) keeps one handler for that channel while useRef dispatches to the latest closure. Ordinary rebuilds therefore preserve the handler, view replacement moves it, and dismissal clears it. The native row also disables hit interception on its decorative icon container, preserving the row as the single accessible action while making icon, label, and edge taps reach the control.

Evidence at this exact head:

  • Focused Dart lifecycle suite: 2/2 PASS. Restoring the old [viewId, onSelected] dependency causally failed the rebuild regression; restoring the candidate passed.
  • Focused native whole-row hit-target XCTest: PASS on an iPhone 17 Pro / iOS 26.5 simulator. Re-enabling icon-container interaction causally failed the test; restoring the candidate passed.
  • Focused Dart format/analyze: PASS.
  • Attached before/after recordings cover the visible failure and the repaired Edit, Copy, reopen, and outside-dismiss journeys.
  • Exact-head Mobile, Mobile Swift domain/results, DCO, Semgrep, and zizmor checks are green.

Non-blocking confidence gaps, owned by release/tooling rather than this author:

  • CI does not currently execute RunnerTests.xctest; the changed focused XCTest was run independently, but not the entire RunnerTests suite.
  • Physical-device clipboard-content behavior and VoiceOver traversal were not independently repeated. Static ownership/semantics, causal mutation tests, simulator behavior, and the supplied recording leave low residual risk; release/dogfood should retain those checks.

A new head invalidates this approval until its delta is reviewed.

brow added a commit that referenced this pull request Sep 19, 2026
* origin/main:
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)

Signed-off-by: Tom Brow <tomb@block.xyz>
wpfleger96 pushed a commit that referenced this pull request Sep 21, 2026
* origin/main: (75 commits)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  fix(web): route mobile invite downloads to app stores (#7702)
  feat(mobile): show build number with version in settings (#7697)
  release(mobile-infra): buzz-push-gateway 0.3.0 (#7685)
  Add authenticated WebSocket recovery telemetry (#7546)
  Instrument database pool roles (#7356)
  ...

# Conflicts:
#	crates/buzz-db/src/runtime/migration.rs
wpfleger96 pushed a commit that referenced this pull request Sep 21, 2026
* origin/main: (81 commits)
  fix(mobile): avoid opening empty threads on message tap (#7756)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  fix(web): route mobile invite downloads to app stores (#7702)
  feat(mobile): show build number with version in settings (#7697)
  release(mobile-infra): buzz-push-gateway 0.3.0 (#7685)
  Add authenticated WebSocket recovery telemetry (#7546)
  ...

Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Sep 21, 2026
* origin/main: (75 commits)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  fix(web): route mobile invite downloads to app stores (#7702)
  feat(mobile): show build number with version in settings (#7697)
  release(mobile-infra): buzz-push-gateway 0.3.0 (#7685)
  Add authenticated WebSocket recovery telemetry (#7546)
  Instrument database pool roles (#7356)
  ...
wpfleger96 pushed a commit that referenced this pull request Sep 21, 2026
* origin/main: (75 commits)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  fix(web): route mobile invite downloads to app stores (#7702)
  feat(mobile): show build number with version in settings (#7697)
  release(mobile-infra): buzz-push-gateway 0.3.0 (#7685)
  Add authenticated WebSocket recovery telemetry (#7546)
  Instrument database pool roles (#7356)
  ...
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
atishpatel pushed a commit to atishpatel/buzz that referenced this pull request Sep 21, 2026
…p-20260915

* origin/main: (28 commits)
  fix(mobile): avoid opening empty threads on message tap (block#7756)
  fix(workflows): make deletion persistent and retryable (block#7735)
  fix(mobile): preserve thread replies through refresh failures (block#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (block#7758)
  fix(relay): exclude ephemeral activity from message quota (block#7736)
  release: push gateway chart 0.3.1 (block#7749)
  fix(push): label plaintext push gateway service as HTTP (block#7717)
  Replace personal and internal data in desktop test fixtures (block#7748)
  Add mobile VISION (block#7710)
  fix(mobile): keep relay sessions stable during push lease updates (block#7745)
  fix(desktop): keep managed agent avatars usable across communities (block#7732)
  fix(mobile): fail open when age checks are unavailable (block#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (block#7709)
  fix(mobile): temporarily disable age gating (block#7708)
  feat(db): expose connection setup metrics (block#7286)
  Isolate S3 storage metrics from the relay (block#7543)
  fix(web): route mobile invite downloads to app stores (block#7702)
  feat(mobile): show build number with version in settings (block#7697)
  release(mobile-infra): buzz-push-gateway 0.3.0 (block#7685)
  Add authenticated WebSocket recovery telemetry (block#7546)
  ...

Signed-off-by: Brainy Bumble <0ed7657b57c0e8a9f5288390dd6c8d5d0a3a06abe9b01b9006814f52077d6cdf@buzz.block.builderlab.xyz>
shellz-n-stuff added a commit that referenced this pull request Sep 21, 2026
…ecurity

* origin/main: (22 commits)
  feat(relay): add admin HTTP routes for member restriction management (#7302)
  fix(relay): fire kick live side effects at convergence; persist target; fence re-add race with held lock (#7298)
  feat(relay): add atomic complete read-state snapshots (#7572)
  fix(desktop): register macOS badges for new and existing installs (#7783)
  fix(mobile): avoid opening empty threads on message tap (#7756)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  ...

Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
TheSentinel454 added a commit that referenced this pull request Sep 21, 2026
…ness-overload

* origin/main: (74 commits)
  feat(relay): add admin HTTP routes for member restriction management (#7302)
  fix(relay): fire kick live side effects at convergence; persist target; fence re-add race with held lock (#7298)
  feat(relay): add atomic complete read-state snapshots (#7572)
  fix(desktop): register macOS badges for new and existing installs (#7783)
  fix(mobile): avoid opening empty threads on message tap (#7756)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  ...

Signed-off-by: tornquist <tornquist@squareup.com>
wpfleger96 pushed a commit that referenced this pull request Sep 21, 2026
…rcement

* origin/main: (87 commits)
  feat(relay): add admin HTTP routes for member restriction management (#7302)
  fix(relay): fire kick live side effects at convergence; persist target; fence re-add race with held lock (#7298)
  feat(relay): add atomic complete read-state snapshots (#7572)
  fix(desktop): register macOS badges for new and existing installs (#7783)
  fix(mobile): avoid opening empty threads on message tap (#7756)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)
  fix(desktop): keep managed agent avatars usable across communities (#7732)
  fix(mobile): fail open when age checks are unavailable (#7714)
  fix(ci): don't run desktop tests for purely mobile client changes (#7709)
  fix(mobile): temporarily disable age gating (#7708)
  feat(db): expose connection setup metrics (#7286)
  Isolate S3 storage metrics from the relay (#7543)
  ...

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>

# Conflicts:
#	crates/buzz-auth/src/nip98.rs
#	crates/buzz-relay/Cargo.toml
brow added a commit that referenced this pull request Sep 22, 2026
…-dev

* origin/main:
  fix(desktop): bound startup request bursts and recover quota refusals (#7790)
  fix(audit): frame hash inputs with TLV (#7492)
  fix(admin): allow cold storage worker DB startup (#7770)
  feat(relay): add admin HTTP routes for member restriction management (#7302)
  fix(relay): fire kick live side effects at convergence; persist target; fence re-add race with held lock (#7298)
  feat(relay): add atomic complete read-state snapshots (#7572)
  fix(desktop): register macOS badges for new and existing installs (#7783)
  fix(mobile): avoid opening empty threads on message tap (#7756)
  fix(workflows): make deletion persistent and retryable (#7735)
  fix(mobile): preserve thread replies through refresh failures (#7757)
  fix(mobile): keep iOS message menu actions responsive after rebuilds (#7758)
  fix(relay): exclude ephemeral activity from message quota (#7736)
  release: push gateway chart 0.3.1 (#7749)
  fix(push): label plaintext push gateway service as HTTP (#7717)
  Replace personal and internal data in desktop test fixtures (#7748)
  Add mobile VISION (#7710)
  fix(mobile): keep relay sessions stable during push lease updates (#7745)

Signed-off-by: Tom Brow <tomb@block.xyz>
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.

2 participants