fix(mobile): stop blank Tailscale Adding carnival - #779
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Greptile SummaryThis PR updates the mobile Tailscale discovery flow for adding computers. The main changes are:
|
| Filename | Overview |
|---|---|
| hermes-mobile/src/components/TailscaleDiscoveryBanner.tsx | Adds local per-discovery add state so only the tapped Tailscale chip shows Adding…; behavior depends on callers returning the async add promise. |
| hermes-mobile/src/components/ConnectMacGate.tsx | Promotes Tailscale candidates above Wi-Fi/QR loaders and passes the async add handler directly in the fresh-user gate. |
| hermes-mobile/src/components/ChatConnectionPanel.tsx | Stops passing global probing as add state, but the onAddTailscaleComputer contract still drops async completion so chip loading clears immediately in real chat callers. |
| hermes-mobile/src/screens/SettingsScreen.tsx | Drops the obsolete global adding prop, but still wraps the async Tailscale add call with void, preventing the banner from tracking pending add state. |
| hermes-mobile/src/tests/TailscaleDiscoveryBanner.test.tsx | Adds focused coverage for single-chip Adding… state using a pending promise. |
| hermes-mobile/src/tests/ChatConnectionPanel.test.tsx | Covers Tailscale banner visibility and verifies global probing no longer blanks sibling chip labels. |
| hermes-mobile/src/tests/ConnectMacGate.test.tsx | Adds regression coverage that Tailscale candidates suppress competing fresh-user Wi-Fi/QR loaders. |
| plan.md | Updates live coordination state for the paid-user Tailscale connect UX task. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
hermes-mobile/src/components/ChatConnectionPanel.tsx:276
**Return the add promise**
`TailscaleDiscoveryBanner` now keeps `Adding…` visible only while the `onAdd` promise is pending, but this prop is still typed as `void` and real callers wrap `addDiscoveredTailscaleComputer` with `void`. In `ChatScreen` and `SettingsScreen`, pressing a chip clears `addingKey` immediately while the async catalog/select work continues, so the per-chip loading state is not effective outside the gate. Please widen `onAddTailscaleComputer` to return `Promise<void> | void` and return `addDiscoveredTailscaleComputer(discovery)` from the wrappers.
Reviews (1): Last reviewed commit: "test(mobile): remove trailing whitespace" | Re-trigger Greptile
| discoveries={tailscaleDiscoveries} | ||
| adding={tailscaleDiscoveryProbing} | ||
| probing={tailscaleSearching} | ||
| onAdd={onAddTailscaleComputer} |
There was a problem hiding this comment.
Return the add promise
TailscaleDiscoveryBanner now keeps Adding… visible only while the onAdd promise is pending, but this prop is still typed as void and real callers wrap addDiscoveredTailscaleComputer with void. In ChatScreen and SettingsScreen, pressing a chip clears addingKey immediately while the async catalog/select work continues, so the per-chip loading state is not effective outside the gate. Please widen onAddTailscaleComputer to return Promise<void> | void and return addDiscoveredTailscaleComputer(discovery) from the wrappers.
Artifacts
Repro: focused Jest harness for ChatConnectionPanel Tailscale add promise behavior
- Contains supporting evidence from the run (text/tsx; charset=utf-8).
- Keeps the command output available without making the summary code-heavy.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: hermes-mobile/src/components/ChatConnectionPanel.tsx
Line: 276
Comment:
**Return the add promise**
`TailscaleDiscoveryBanner` now keeps `Adding…` visible only while the `onAdd` promise is pending, but this prop is still typed as `void` and real callers wrap `addDiscoveredTailscaleComputer` with `void`. In `ChatScreen` and `SettingsScreen`, pressing a chip clears `addingKey` immediately while the async catalog/select work continues, so the per-chip loading state is not effective outside the gate. Please widen `onAddTailscaleComputer` to return `Promise<void> | void` and return `addDiscoveredTailscaleComputer(discovery)` from the wrappers.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 309d5c17bd
ℹ️ 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".
| - `.github/workflows/mobile-ota.yml` (rollout clamp only: 100=omit flag; 1-99 staged; promote clamp), `hermes-mobile/src/__tests__/releaseSafetyContract.test.ts` (EAS-rejects-100 strings only; leave Leash tab wording), `plan.md` → **terra-ota-rollout-clamp** (T-OTA-ROLLOUT-EAS-99; evidence run 29889285465) (2026-07-22T04:12:00Z) | ||
| - `hermes-mobile/src/components/ConnectMacGate.tsx` (always-visible onboarding+Find computers; do not hide for profileScanning), `hermes-mobile/src/__tests__/ConnectMacGate.test.tsx` (profileScanning keeps onboarding), `plan.md` → **cursor-leash-lazy-spinner** (T-LEASH-LAZY-SPINNER stranger OTA unblock) (2026-07-22T03:30:00Z) | ||
| - `hermes-mobile/src/components/ConnectMacGate.tsx` (onboarding visible during bootstrap booting only — keep #755 search collapse), `hermes-mobile/src/__tests__/ConnectMacGate.test.tsx` (bootstrap booting cases), `plan.md` → **cursor-leash-lazy-spinner** (T-LEASH-LAZY-SPINNER unblock stranger CI after #755) (2026-07-22T02:46:01Z) | ||
| - `hermes-mobile/src/components/TailscaleDiscoveryBanner.tsx`, `hermes-mobile/src/components/ConnectMacGate.tsx` (candidate-first discovery state and QR demotion only), `hermes-mobile/src/components/ChatConnectionPanel.tsx` (pass per-candidate add behavior only), `hermes-mobile/src/__tests__/TailscaleDiscoveryBanner.test.tsx`, `hermes-mobile/src/__tests__/ConnectMacGate.test.tsx`, `hermes-mobile/src/__tests__/ChatConnectionPanel.test.tsx`, `plan.md` → **terra-paid-user-connect-ux** (T-PAID-USER-CONNECT-UX-20260722; reclaimed after confirming T-CONNECT-UX/#755 and T-LEASH worktrees were clean, their branches had no open PR, and their last commits were 2026-07-21; do not touch GatewayContext or discovery/profile services) (2026-07-22T13:35:00Z) |
There was a problem hiding this comment.
Respect the existing ConnectMacGate owner
The ownership map above still has active cursor-leash-lazy-spinner claims for hermes-mobile/src/components/ConnectMacGate.tsx and its test, and this new claim/edit takes the same files without an append-only release. In this repo that creates a live multi-owner hot-file collision instead of a block/release handoff, so another agent can overwrite this work or vice versa; add a release/blocked handoff before touching those files.
AGENTS.md reference: AGENTS.md:L24-L26
Useful? React with 👍 / 👎.
| await onAdd(discovery); | ||
| } finally { | ||
| setAddingKey(null); |
There was a problem hiding this comment.
Keep Add chips disabled until the real add finishes
When this banner is used from ChatConnectionPanel or Settings, the supplied callbacks fire-and-forget addDiscoveredTailscaleComputer with void (ChatScreen.tsx:7047-7049, SettingsScreen.tsx:543-545), so await onAdd(discovery) resolves immediately and the finally clears addingKey while the async save/select is still running. In those screens the tapped chip re-enables almost instantly, Adding… is not visible, and a second tap can start another add/switch for the same candidate before the first one completes; return the promise through those callbacks or keep the in-flight state where the async work actually lives.
Useful? React with 👍 / 👎.
|
Also lands: onboarding steps now prefer saved |
9d18d4a to
6e958b0
Compare
Choose computer paste-Tailscale-IP hero copy; coord spacing/#779 slices. Co-authored-by: Cursor <cursoragent@cursor.com>
Choose computer paste-Tailscale-IP hero copy; coord spacing/#779 slices. Co-authored-by: Cursor <cursoragent@cursor.com>
74eaa49 to
ee76f1e
Compare
Choose computer paste-Tailscale-IP hero copy; coord spacing/#779 slices. Co-authored-by: Cursor <cursoragent@cursor.com>
Choose computer paste-Tailscale-IP hero copy; coord spacing/#779 slices. Co-authored-by: Cursor <cursoragent@cursor.com>
de497b2 to
09fb719
Compare
09fb719 to
a1cab25
Compare
c5743b0 to
7e3bce5
Compare
Co-authored-by: Cursor <cursoragent@cursor.com>
Paid-user discovery was rendering every Tailscale chip as Adding while Wi-Fi search and QR competed for attention. Track per-candidate add state, promote Tailscale candidates as the primary path, and demote QR plus competing Wi-Fi loaders when candidates are present. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
When MacBook is unreachable, steps said Start Hermes on Mac mini because primaryTailscaleLabel won. Prefer the saved macLabel. Co-authored-by: Cursor <cursoragent@cursor.com>
7e3bce5 to
9de5976
Compare
|
cursor-recovery: will update branch onto main and squash-merge (all required checks green). |
|
OTA freeze (2026-07-23): Expo billing declined (~$78). Do not publish preview or production OTA until further notice. |
Summary
Adding…; sibling chips keep host names.addingprop.Test plan
npm run typechecklatest.jsonwas skipped while phone in use)Made with Cursor