Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,10 @@ import {
selectThreadPreviewMiniPlayer,
usePreviewMiniPlayerStore,
} from "../previewMiniPlayerStore";
import { pullRequestPanelContext } from "./pullRequest/pullRequestDetail.logic";
import {
pullRequestPanelContext,
threadPullRequestPanelTarget,
} from "./pullRequest/pullRequestDetail.logic";
import { PullRequestDetailPanel } from "./pullRequest/PullRequestDetailPanel";
import { PullRequestDetailGhost } from "./pullRequest/PullRequestGhosts";
import { PullRequestsUnavailableState } from "./pullRequest/PullRequestsUnavailableState";
Expand Down Expand Up @@ -6613,12 +6616,20 @@ export default function ChatView(props: ChatViewProps) {
},
);
}, [activeThreadReferenceCopyTarget]);
const pullRequestPanelTarget = activeThread
? threadPullRequestPanelTarget({
projectId: activeThread.projectId,
pullRequests: visiblePullRequests,
linkedPullRequest: linkedThreadPullRequest,
branchPullRequest: activeThreadShell?.branchPullRequest ?? activeThread.branchPullRequest,
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
})
: null;
const addPullRequestSurface = useCallback(() => {
if (!supportsPullRequests || activeThreadRef === null || linkedThreadPullRequest === null)
if (!supportsPullRequests || activeThreadRef === null || pullRequestPanelTarget === null)
return;
useRightPanelStore.getState().openPullRequest(activeThreadRef, linkedThreadPullRequest);
}, [activeThreadRef, linkedThreadPullRequest, supportsPullRequests]);
const pullRequestSurfaceAvailable = supportsPullRequests && linkedThreadPullRequest !== null;
useRightPanelStore.getState().openPullRequest(activeThreadRef, pullRequestPanelTarget);
}, [activeThreadRef, pullRequestPanelTarget, supportsPullRequests]);
const pullRequestSurfaceAvailable = supportsPullRequests && pullRequestPanelTarget !== null;
const supportsSettlement = serverConfig?.environment.capabilities.threadSettlement === true;
const supportsSnooze = serverConfig?.environment.capabilities.threadSnooze === true;
const supportsPinning = serverConfig?.environment.capabilities.threadPinning === true;
Expand Down Expand Up @@ -10339,6 +10350,8 @@ export default function ChatView(props: ChatViewProps) {
projectId: activeThread.projectId,
pullRequests: visiblePullRequests,
linkedPullRequest: linkedThreadPullRequest,
branchPullRequest:
activeThreadShell?.branchPullRequest ?? activeThread.branchPullRequest,
},
renderedRightPanelSurface,
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
isStackedPullRequestBase,
loadingPullRequestCheckoutCommand,
pullRequestPanelContext,
threadPullRequestPanelTarget,
latestPullRequestReviewOutcomes,
newestPullRequestCommitAt,
mergePullRequestThreadComments,
Expand Down Expand Up @@ -1535,6 +1536,45 @@ describe("pull request panel context beside a thread", () => {
);
expect(pullRequestPanelContext({ projectId: null }, surface(3))).toBe("page");
});

describe("the Pull request entry's target", () => {
const legacy = (number: number) => ({
projectId: ProjectId.make("proj-a"),
repository: "pingdotgg/t3code",
number,
url: `https://github.com/pingdotgg/t3code/pull/${number}`,
});

it("opens a linked pull request the legacy field never named, ahead of the branch PR", () => {
expect(
threadPullRequestPanelTarget({
projectId: "proj-a",
pullRequests: [link(15046, { source: "agent" })],
linkedPullRequest: null,
branchPullRequest: legacy(30),
}),
).toEqual({ ...legacy(15046), host: "github.com" });
});

it("reuses the legacy reference only for the same pull request on the same host", () => {
const linkedPullRequest = legacy(15046);
const onHost = (host: string) =>
threadPullRequestPanelTarget({
projectId: "proj-a",
pullRequests: [link(15046, { host, url: `https://${host}/pingdotgg/t3code/pull/15046` })],
linkedPullRequest,
});
expect(onHost("github.com")).toBe(linkedPullRequest);
expect(onHost("github.example.com")).toMatchObject({ host: "github.example.com" });
});

it("falls back to the branch pull request when the thread holds no link", () => {
expect(
threadPullRequestPanelTarget({ projectId: "proj-a", branchPullRequest: legacy(3) }),
).toEqual(legacy(3));
expect(threadPullRequestPanelTarget({ projectId: "proj-a", pullRequests: [] })).toBeNull();
});
});
});

describe("which actions need the host read again after they run", () => {
Expand Down
29 changes: 29 additions & 0 deletions apps/web/src/components/pullRequest/pullRequestDetail.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
type VcsRef,
} from "@t3tools/contracts";
import {
legacyThreadPullRequestKey,
resolveThreadCurrentPullRequestLink,
threadPullRequestKeysEqual,
visibleThreadPullRequests,
} from "@t3tools/shared/threadPullRequests";
Expand Down Expand Up @@ -236,6 +238,33 @@ export function pullRequestPanelContext(
: "page";
}

export function threadPullRequestPanelTarget(thread: {
readonly projectId: string;
readonly pullRequests?: ReadonlyArray<ThreadPullRequestLink> | undefined;
readonly linkedPullRequest?: ThreadLinkedPullRequest | null | undefined;
readonly branchPullRequest?: ThreadLinkedPullRequest | null | undefined;
}) {
const current = resolveThreadCurrentPullRequestLink(thread.pullRequests ?? []);
const legacy = thread.linkedPullRequest;
if (
current !== null &&
legacy != null &&
threadPullRequestKeysEqual(current, legacyThreadPullRequestKey(legacy))
) {
return legacy;
}
if (current !== null) {
return {
projectId: thread.projectId,
host: current.host,
repository: current.repository,
number: current.number,
url: current.url,
};
}
return legacy ?? thread.branchPullRequest ?? null;
}

/** Names where a pull-request task will land, without letting each surface guess independently. */
export function pullRequestHandoffLabels(inThisThread: boolean) {
return inThisThread
Expand Down
Loading