feat(app): Share-dialog hub CTA + local-only link confirm (0290) - #449
feat(app): Share-dialog hub CTA + local-only link confirm (0290)#449crs48 wants to merge 1 commit into
Conversation
With no hub connected the Share dialog dead-ended at explanatory text; it
now explains why sharing needs a hub and offers a "Connect a hub…" button
that opens the status bar's connection panel. That panel gains an inline
hub-URL connect form (persisted like Settings → Network, reload applies),
and is portaled out of the status-bar island — the floating-islands shell's
overflow-hidden was clipping the popover into invisibility.
Links minted on a private/LAN hub are labelled "Local only", and Copy/QR
arm on first click ("Copy anyway" / "QR anyway") so a link that only works
on the local network isn't handed out as if it were public. Generation
stays enabled — LAN/QR handoff is legitimate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
🖼️ UI changes in this PRNo visual differences detected in the changed UI. |
|
Preview: https://xnet.fyi/pr/449/app/ |
|
Closing in favour of #658, which rebuilds both of these items against today's surfaces. This diff could not be rebased: its main target, That turned out to be good news for the feature: building it in Both 0290 items (the |
…(0410) (#658) Implements exploration `0410_[_]_OPEN_PR_TRIAGE_AND_THE_STRANDED_BRANCH_PROBLEM.md`, written in the previous turn. ## What this closes out Eight PRs were open, the oldest from March. Checking each one's **actual diff against `main`** (rather than its description) found that four described work already in `main`, re-derived and landed weeks later by another route. | PR | Age | Action taken | | --- | --- | --- | | #400 | 24d | **Closed** — fix landed on main in a better form; branch predates 0391 and would have deleted `NodeLineRunner` | | #9 | 145d | **Closed** — draft; `apps/electron/src/renderer/workspace/` no longer exists | | #595 | 11d | **Closed** — byte-identical to main (`fbc2965a2`) | | #463 | 20d | **Closed** — main has a longer, `[x]` version of 0298 | | #13 | 141d | **Closed** — both fixes on main verbatim | | #505 | 17d | **Merged** — exploration 0318 + scale bench | | #389 | 25d | **Merged** — exploration 0270 | | #449 | 20d | **Rebuilt here** — see below | `#400` was the load-bearing one: `git diff origin/main pr400 -- packages/devkit/src/command-runner.ts` showed ~150 lines of *deletion* covering the whole 0391 streaming agent seam. Only its `CONFLICTING` state had prevented that. `#505`'s `build-and-smoke-test` went green on a rebase, confirming it was branch staleness rather than the diff. ## The #449 rebuild (0290 bugs #2 and #3) The original patched `apps/web/src/workbench/SyncStatus.tsx`, which 0406 deleted; the component now lives in `packages/workbench`, so the rebuild lands on **desktop and web at once**. - `WorkbenchHost` gains a `hub` capability (`configuredUrl` / `connect`) so the shell can offer a way out of the disconnected state without importing either app's `hub-url` module. `connect` returns a reason string on rejection — never a silent no-op. - `SyncStatus` exports `openSyncStatusPanel()`; the desktop popover and mobile sheet both listen. The panel shows an inline hub-URL form while there is no hub. - `ShareDialog`'s `!ready` branch explains why a hub is needed and offers **Connect a hub…**; private-hub links now confirm before copying. - Adds `normalizeHubUrl` to the electron renderer's `hub-url` mirror (+4 unit tests), so a malformed URL is rejected loudly rather than persisted. Verified by driving the real app against a local hub — the CTA closes the dialog and opens the panel; an invalid URL shows an error and persists nothing; `https://hub.xnet.fyi/` normalises to `wss://hub.xnet.fyi`; a `localhost` link's first Copy click asks "Copy local-only link?" and writes nothing, the second copies. No console errors. 0290 is now `[-]` at 11/20. ## Stopping the recurrence Time-to-merge for the last 20 merged PRs was **0 hours median, 1 hour max** — there is no review queue, so a PR that outlives its session is abandoned, not pending. - `.github/workflows/stale.yml` — warns at 14d, closes at 21d, `keep-open` exempts. Named consumer (the maintainer, weekly) and a decidable pass condition, per AGENTS.md. - Fixed the `/explore` next-number command, which read only the working tree and so handed out numbers already claimed on branches. Seven explorations were found stranded that way. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Implements the two remaining UI items from
docs/explorations/0290_[_]_SHARE_LINK_GENERATION_FAILURE_MODES.md(bugs #2 and #3, both Option A). Follows up on #448.No-hub dead-end → "Connect a hub…" CTA
ShareDialog(!ready) now explains why sharing needs a hub and offers a Connect a hub… button that closes the dialog and opens the status bar's connection panel (newopenSyncStatusPanel()event inSyncStatus.tsx; the mobile sheet listens too).hub-url.tshelpers as Settings → Network and reloading to apply — so the CTA genuinely lands you connected, per the exploration's validation criterion.overflow-hidden, which swallowed the sync-status popover entirely (it opened invisibly). The popover is now portaled into.wb-root(fixed-position above the chip; portal stays inside the shell root so.dark .wb-roottokens keep working) and usesbg-island-pop— the previousbg-surfaceresolved to transparent (same dead token 0287 fixed for modals).Private-hub links → "Local only" + confirm
isPrivateHubHost(hubHttpUrl).Verification
apps/webtypecheck clean; newShareDialog.test.tsx(CTA event + arming + public-hub no-confirm) plus FormShareBar/share-links/sync-format suites: 41 tests green (re-run after rebasing onto post-Enforce demo-hub storage guardrails (0291) + workspace share links (0290) #448 main).ws://localhost:4444): CTA → panel → connect → reload → chip "Hub: connected · healthy" → New link mintshttp://localhost:4444/s/…with Local-only chip; Copy/QR require the confirm click; QR renders after confirming.🤖 Generated with Claude Code