| author | |
| committer | |
| log | f90b77d80971ea4855a42abfc89ce85466e1accb |
| tree | 2eeebbb3aedcf0ec56efe898786c718e82be8bc6 |
| parent | 237d51e6cd2f935d3ddced4efe8fcd4a5d697e43 |
| signature | Signed by PGP key B5690EEEBB952194 |
3 files changed, 87 insertions(+), 5 deletions(-)
apps/web/src/components/ChatView.tsx+18-5| ... | @@ -266,7 +266,10 @@ import { | ... | @@ -266,7 +266,10 @@ import { |
| 266 | selectThreadPreviewMiniPlayer, | 266 | selectThreadPreviewMiniPlayer, |
| 267 | usePreviewMiniPlayerStore, | 267 | usePreviewMiniPlayerStore, |
| 268 | } from "../previewMiniPlayerStore"; | 268 | } from "../previewMiniPlayerStore"; |
| 269 | import { pullRequestPanelContext } from "./pullRequest/pullRequestDetail.logic"; | 269 | import { |
| 270 | pullRequestPanelContext, | ||
| 271 | threadPullRequestPanelTarget, | ||
| 272 | } from "./pullRequest/pullRequestDetail.logic"; | ||
| 270 | import { PullRequestDetailPanel } from "./pullRequest/PullRequestDetailPanel"; | 273 | import { PullRequestDetailPanel } from "./pullRequest/PullRequestDetailPanel"; |
| 271 | import { PullRequestDetailGhost } from "./pullRequest/PullRequestGhosts"; | 274 | import { PullRequestDetailGhost } from "./pullRequest/PullRequestGhosts"; |
| 272 | import { PullRequestsUnavailableState } from "./pullRequest/PullRequestsUnavailableState"; | 275 | import { PullRequestsUnavailableState } from "./pullRequest/PullRequestsUnavailableState"; |
| ... | @@ -6776,12 +6779,20 @@ export default function ChatView(props: ChatViewProps) { | ... | @@ -6776,12 +6779,20 @@ export default function ChatView(props: ChatViewProps) { |
| 6776 | }, | 6779 | }, |
| 6777 | ); | 6780 | ); |
| 6778 | }, [activeThreadReferenceCopyTarget]); | 6781 | }, [activeThreadReferenceCopyTarget]); |
| 6782 | const pullRequestPanelTarget = activeThread | ||
| 6783 | ? threadPullRequestPanelTarget({ | ||
| 6784 | projectId: activeThread.projectId, | ||
| 6785 | pullRequests: visiblePullRequests, | ||
| 6786 | linkedPullRequest: linkedThreadPullRequest, | ||
| 6787 | branchPullRequest: activeThreadShell?.branchPullRequest ?? activeThread.branchPullRequest, | ||
| 6788 | }) | ||
| 6789 | : null; | ||
| 6779 | const addPullRequestSurface = useCallback(() => { | 6790 | const addPullRequestSurface = useCallback(() => { |
| 6780 | if (!supportsPullRequests || activeThreadRef === null || linkedThreadPullRequest === null) | 6791 | if (!supportsPullRequests || activeThreadRef === null || pullRequestPanelTarget === null) |
| 6781 | return; | 6792 | return; |
| 6782 | useRightPanelStore.getState().openPullRequest(activeThreadRef, linkedThreadPullRequest); | 6793 | useRightPanelStore.getState().openPullRequest(activeThreadRef, pullRequestPanelTarget); |
| 6783 | }, [activeThreadRef, linkedThreadPullRequest, supportsPullRequests]); | 6794 | }, [activeThreadRef, pullRequestPanelTarget, supportsPullRequests]); |
| 6784 | const pullRequestSurfaceAvailable = supportsPullRequests && linkedThreadPullRequest !== null; | 6795 | const pullRequestSurfaceAvailable = supportsPullRequests && pullRequestPanelTarget !== null; |
| 6785 | const supportsSettlement = serverConfig?.environment.capabilities.threadSettlement === true; | 6796 | const supportsSettlement = serverConfig?.environment.capabilities.threadSettlement === true; |
| 6786 | const supportsSnooze = serverConfig?.environment.capabilities.threadSnooze === true; | 6797 | const supportsSnooze = serverConfig?.environment.capabilities.threadSnooze === true; |
| 6787 | const supportsPinning = serverConfig?.environment.capabilities.threadPinning === true; | 6798 | const supportsPinning = serverConfig?.environment.capabilities.threadPinning === true; |
| ... | @@ -10535,6 +10546,8 @@ export default function ChatView(props: ChatViewProps) { | ... | @@ -10535,6 +10546,8 @@ export default function ChatView(props: ChatViewProps) { |
| 10535 | projectId: activeThread.projectId, | 10546 | projectId: activeThread.projectId, |
| 10536 | pullRequests: visiblePullRequests, | 10547 | pullRequests: visiblePullRequests, |
| 10537 | linkedPullRequest: linkedThreadPullRequest, | 10548 | linkedPullRequest: linkedThreadPullRequest, |
| 10549 | branchPullRequest: | ||
| 10550 | activeThreadShell?.branchPullRequest ?? activeThread.branchPullRequest, | ||
| 10538 | }, | 10551 | }, |
| 10539 | renderedRightPanelSurface, | 10552 | renderedRightPanelSurface, |
| 10540 | )} | 10553 | )} |
apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts+40| ... | @@ -35,6 +35,7 @@ import { | ... | @@ -35,6 +35,7 @@ import { |
| 35 | isStackedPullRequestBase, | 35 | isStackedPullRequestBase, |
| 36 | loadingPullRequestCheckoutCommand, | 36 | loadingPullRequestCheckoutCommand, |
| 37 | pullRequestPanelContext, | 37 | pullRequestPanelContext, |
| 38 | threadPullRequestPanelTarget, | ||
| 38 | latestPullRequestReviewOutcomes, | 39 | latestPullRequestReviewOutcomes, |
| 39 | newestPullRequestCommitAt, | 40 | newestPullRequestCommitAt, |
| 40 | mergePullRequestThreadComments, | 41 | mergePullRequestThreadComments, |
| ... | @@ -1535,6 +1536,45 @@ describe("pull request panel context beside a thread", () => { | ... | @@ -1535,6 +1536,45 @@ describe("pull request panel context beside a thread", () => { |
| 1535 | ); | 1536 | ); |
| 1536 | expect(pullRequestPanelContext({ projectId: null }, surface(3))).toBe("page"); | 1537 | expect(pullRequestPanelContext({ projectId: null }, surface(3))).toBe("page"); |
| 1537 | }); | 1538 | }); |
| 1539 | |||
| 1540 | describe("the Pull request entry's target", () => { | ||
| 1541 | const legacy = (number: number) => ({ | ||
| 1542 | projectId: ProjectId.make("proj-a"), | ||
| 1543 | repository: "pingdotgg/t3code", | ||
| 1544 | number, | ||
| 1545 | url: `https://github.com/pingdotgg/t3code/pull/${number}`, | ||
| 1546 | }); | ||
| 1547 | |||
| 1548 | it("opens a linked pull request the legacy field never named, ahead of the branch PR", () => { | ||
| 1549 | expect( | ||
| 1550 | threadPullRequestPanelTarget({ | ||
| 1551 | projectId: "proj-a", | ||
| 1552 | pullRequests: [link(15046, { source: "agent" })], | ||
| 1553 | linkedPullRequest: null, | ||
| 1554 | branchPullRequest: legacy(30), | ||
| 1555 | }), | ||
| 1556 | ).toEqual({ ...legacy(15046), host: "github.com" }); | ||
| 1557 | }); | ||
| 1558 | |||
| 1559 | it("reuses the legacy reference only for the same pull request on the same host", () => { | ||
| 1560 | const linkedPullRequest = legacy(15046); | ||
| 1561 | const onHost = (host: string) => | ||
| 1562 | threadPullRequestPanelTarget({ | ||
| 1563 | projectId: "proj-a", | ||
| 1564 | pullRequests: [link(15046, { host, url: `https://${host}/pingdotgg/t3code/pull/15046` })], | ||
| 1565 | linkedPullRequest, | ||
| 1566 | }); | ||
| 1567 | expect(onHost("github.com")).toBe(linkedPullRequest); | ||
| 1568 | expect(onHost("github.example.com")).toMatchObject({ host: "github.example.com" }); | ||
| 1569 | }); | ||
| 1570 | |||
| 1571 | it("falls back to the branch pull request when the thread holds no link", () => { | ||
| 1572 | expect( | ||
| 1573 | threadPullRequestPanelTarget({ projectId: "proj-a", branchPullRequest: legacy(3) }), | ||
| 1574 | ).toEqual(legacy(3)); | ||
| 1575 | expect(threadPullRequestPanelTarget({ projectId: "proj-a", pullRequests: [] })).toBeNull(); | ||
| 1576 | }); | ||
| 1577 | }); | ||
| 1538 | }); | 1578 | }); |
| 1539 | 1579 | ||
| 1540 | describe("which actions need the host read again after they run", () => { | 1580 | describe("which actions need the host read again after they run", () => { |
apps/web/src/components/pullRequest/pullRequestDetail.logic.ts+29| ... | @@ -27,6 +27,8 @@ import { | ... | @@ -27,6 +27,8 @@ import { |
| 27 | type VcsRef, | 27 | type VcsRef, |
| 28 | } from "@t3tools/contracts"; | 28 | } from "@t3tools/contracts"; |
| 29 | import { | 29 | import { |
| 30 | legacyThreadPullRequestKey, | ||
| 31 | resolveThreadCurrentPullRequestLink, | ||
| 30 | threadPullRequestKeysEqual, | 32 | threadPullRequestKeysEqual, |
| 31 | visibleThreadPullRequests, | 33 | visibleThreadPullRequests, |
| 32 | } from "@t3tools/shared/threadPullRequests"; | 34 | } from "@t3tools/shared/threadPullRequests"; |
| ... | @@ -237,6 +239,33 @@ export function pullRequestPanelContext( | ... | @@ -237,6 +239,33 @@ export function pullRequestPanelContext( |
| 237 | : "page"; | 239 | : "page"; |
| 238 | } | 240 | } |
| 239 | 241 | ||
| 242 | export function threadPullRequestPanelTarget(thread: { | ||
| 243 | readonly projectId: string; | ||
| 244 | readonly pullRequests?: ReadonlyArray<ThreadPullRequestLink> | undefined; | ||
| 245 | readonly linkedPullRequest?: ThreadLinkedPullRequest | null | undefined; | ||
| 246 | readonly branchPullRequest?: ThreadLinkedPullRequest | null | undefined; | ||
| 247 | }) { | ||
| 248 | const current = resolveThreadCurrentPullRequestLink(thread.pullRequests ?? []); | ||
| 249 | const legacy = thread.linkedPullRequest; | ||
| 250 | if ( | ||
| 251 | current !== null && | ||
| 252 | legacy != null && | ||
| 253 | threadPullRequestKeysEqual(current, legacyThreadPullRequestKey(legacy)) | ||
| 254 | ) { | ||
| 255 | return legacy; | ||
| 256 | } | ||
| 257 | if (current !== null) { | ||
| 258 | return { | ||
| 259 | projectId: thread.projectId, | ||
| 260 | host: current.host, | ||
| 261 | repository: current.repository, | ||
| 262 | number: current.number, | ||
| 263 | url: current.url, | ||
| 264 | }; | ||
| 265 | } | ||
| 266 | return legacy ?? thread.branchPullRequest ?? null; | ||
| 267 | } | ||
| 268 | |||
| 240 | /** Names where a pull-request task will land, without letting each surface guess independently. */ | 269 | /** Names where a pull-request task will land, without letting each surface guess independently. */ |
| 241 | export function pullRequestHandoffLabels(inThisThread: boolean) { | 270 | export function pullRequestHandoffLabels(inThisThread: boolean) { |
| 242 | return inThisThread | 271 | return inThisThread |