authorgravatar for 269035359+t3-code[bot]@users.noreply.github.comt3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> 2026-08-12 14:32:44-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-12 14:32:44-04:00
log8d24b5131f439d11876815996df41a57d791d3ad
treef544028ead7304bbced62bdbf68a72992e9cab0c
parent770946d026208359450bf94083ad807d469d9f07
signature Signed by PGP key B5690EEEBB952194

fix(web): open modified PR clicks in browser (#6278)

Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com> Co-authored-by: maria <254055478+maria-rcks@users.noreply.github.com>

2 files changed, 23 insertions(+), 1 deletions(-)

apps/web/src/lib/openPullRequestLink.test.ts+12
...@@ -5,6 +5,7 @@ import {...@@ -5,6 +5,7 @@ import {
5 openPullRequestLink,5 openPullRequestLink,
6 parseChangeRequestUrl,6 parseChangeRequestUrl,
7 PullRequestLinkOpenError,7 PullRequestLinkOpenError,
8 shouldOpenPullRequestExternally,
8} from "./openPullRequestLink";9} from "./openPullRequestLink";
910
10describe("openPullRequestLink", () => {11describe("openPullRequestLink", () => {
...@@ -34,6 +35,17 @@ describe("openPullRequestLink", () => {...@@ -34,6 +35,17 @@ describe("openPullRequestLink", () => {
34 });35 });
35});36});
3637
38describe("shouldOpenPullRequestExternally", () => {
39 it("uses the browser for command-click and control-click", () => {
40 expect(shouldOpenPullRequestExternally({ metaKey: true, ctrlKey: false })).toBe(true);
41 expect(shouldOpenPullRequestExternally({ metaKey: false, ctrlKey: true })).toBe(true);
42 });
43
44 it("keeps an unmodified click in the pull request view", () => {
45 expect(shouldOpenPullRequestExternally({ metaKey: false, ctrlKey: false })).toBe(false);
46 });
47});
48
37describe("parseChangeRequestUrl", () => {49describe("parseChangeRequestUrl", () => {
38 it("reads a GitHub pull request", () => {50 it("reads a GitHub pull request", () => {
39 expect(parseChangeRequestUrl("https://github.com/T3Tools/T3Code/pull/123")).toEqual({51 expect(parseChangeRequestUrl("https://github.com/T3Tools/T3Code/pull/123")).toEqual({
apps/web/src/lib/openPullRequestLink.ts+11-1
...@@ -173,10 +173,19 @@ export function findProjectForChangeRequest(...@@ -173,10 +173,19 @@ export function findProjectForChangeRequest(
173 * should still be reading it afterwards. Any change request opens there, not only the thread's173 * should still be reading it afterwards. Any change request opens there, not only the thread's
174 * own, since the panel is told which one to show.174 * own, since the panel is told which one to show.
175 */175 */
176export function shouldOpenPullRequestExternally(
177 event: Pick<MouseEvent<HTMLElement>, "metaKey" | "ctrlKey">,
178): boolean {
179 return event.metaKey || event.ctrlKey;
180}
181
176export function useOpenChangeRequestLink(182export function useOpenChangeRequestLink(
177 threadRef?: ScopedThreadRef,183 threadRef?: ScopedThreadRef,
178): (184): (
179 event: Pick<MouseEvent<HTMLElement>, "preventDefault" | "stopPropagation">,185 event: Pick<
186 MouseEvent<HTMLElement>,
187 "preventDefault" | "stopPropagation" | "metaKey" | "ctrlKey"
188 >,
180 targetUrl: string,189 targetUrl: string,
181 targetThreadRef?: ScopedThreadRef,190 targetThreadRef?: ScopedThreadRef,
182) => boolean {191) => boolean {
...@@ -186,6 +195,7 @@ export function useOpenChangeRequestLink(...@@ -186,6 +195,7 @@ export function useOpenChangeRequestLink(
186 const primaryEnvironmentId = usePrimaryEnvironmentId();195 const primaryEnvironmentId = usePrimaryEnvironmentId();
187 return useCallback(196 return useCallback(
188 (event, targetUrl, targetThreadRef) => {197 (event, targetUrl, targetThreadRef) => {
198 if (shouldOpenPullRequestExternally(event)) return false;
189 const resolvedThreadRef = targetThreadRef ?? threadRef;199 const resolvedThreadRef = targetThreadRef ?? threadRef;
190 const environmentId = resolvedThreadRef?.environmentId ?? primaryEnvironmentId;200 const environmentId = resolvedThreadRef?.environmentId ?? primaryEnvironmentId;
191 if (201 if (