Skip to content

feat(web): copy a link to a thread - #7902

Open
fbehrens wants to merge 1 commit into
pingdotgg:mainfrom
fbehrens:feat/copy-thread-link
Open

feat(web): copy a link to a thread#7902
fbehrens wants to merge 1 commit into
pingdotgg:mainfrom
fbehrens:feat/copy-thread-link

Conversation

@fbehrens

@fbehrens fbehrens commented Aug 22, 2026

Copy link
Copy Markdown

Problem

In a browser, a thread's URL is its link — you can copy it out of the address bar. The desktop app is served from t3code://app and has no address bar, and nothing in the UI exposes a thread's address, so there is no way to get a link to a thread out of desktop at all.

Change

Thread context menus now offer Copy → Link. The sidebar row menu and the chat header menu share one builder, so both surfaces get it.

resolveThreadLink picks the base the same way a user would: the client's own web origin when there is one (browser and hosted app), otherwise the address this client reaches the environment at, which is the T3 server that owns the thread — localhost for a server on this machine, the tunnel host for T3 Connect. When neither is an http(s) origin the item is hidden rather than copying something that cannot be opened.

The link is not a share link: the other device still has to reach that address and be paired with the environment. docs/user/thread-sidebar.md says so explicitly.

Mobile is deliberately untouched — it has no thread copy actions at all, so there is no parity to keep.

Before / after

Sidebar thread context menu, Copy submenu.

Before After

Verification

  • vp test run apps/web/src/threadLink.test.ts apps/web/src/components/threadActionMenu.logic.test.ts — 14 passed
  • tsgo --noEmit in apps/web — clean
  • Lint on the touched files — clean
  • Screenshots above are from a real client: vp run dev against an isolated .t3 home with seeded fixture threads, driven through a browser

Written by Claude Opus 5 (1M context) in T3 Code.


Note

Low Risk
Clipboard and URL construction only; no auth or access-control changes. Links still require environment pairing and network reachability.

Overview
Adds Copy → Link to the shared thread action menu (sidebar and chat header) so desktop users can copy a thread URL without an address bar.

resolveThreadLink uses the browser origin when it is http(s); otherwise it falls back to the environment’s HTTP base (localhost or tunnel). The menu item is hidden when neither is a web origin. Links are not public shares—the recipient still needs reachability and pairing.

User docs in thread-sidebar.md describe the behavior. Mobile copy actions are unchanged.

Reviewed by Cursor Bugbot for commit a0657a6. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add "Copy → Link" thread action in web sidebar and chat header menu

  • Adds buildThreadRoutePath in threadRoutes.ts to build a thread pathname as /{environmentId}/{threadId} with URL-encoded segments.
  • Adds resolveThreadLink and readThreadLink in threadLink.ts to compose a full HTTP(S) URL, preferring window.location.origin and falling back to the environment httpBaseUrl; returns null when no valid origin exists.
  • Registers a new 'copy-link' action with a canCopyLink state flag in buildThreadActionMenuItems (threadActionMenu.logic.ts), wired up in both Sidebar.tsx and useThreadActionMenu.ts using useCopyToClipboard with success/error toasts.
  • Adds a 'link' icon entry in contextMenuFallback.ts and documents the feature in thread-sidebar.md.
  • Risk: the link is only shown when an HTTP(S) origin is resolvable; on non-web runtimes without a valid httpBaseUrl, readThreadLink returns null and the menu item is hidden.

Macroscope summarized a0657a6.

The web client's URL is a working thread link, but the desktop app is served
from t3code://app and has no address bar, so there was no way to get a thread's
address out of it at all.

Thread context menus (sidebar row and chat header, which share one builder) now
offer Copy > Link. In a browser the link uses the client's own origin; on
desktop it falls back to the address this client reaches the environment at, so
it points at the T3 server that owns the thread. When neither is an http(s)
origin the item is hidden rather than copying something that cannot be opened.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f94e5e75-3e93-4f14-ab3c-05ec60d4131c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 22, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Skipped

Macroscope did not run approvability analysis for this PR. Macroscope could not determine whether this PR modifies its approvability configuration, so the PR was not approved automatically. A PR that may change the rules that govern approval is never approved automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant