From e35baf750ffce50ac03f379e7cfca88dd3ccaa2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20O=C5=A1i=C5=86=C5=A1?= Date: Tue, 1 Sep 2026 18:41:53 +0200 Subject: [PATCH] Show the branch a patch is opened against Add it to the patch list byline and the patch page metadata, shown only when it differs from the default branch. The merge activity item now names the real target instead of always naming the default branch. Co-Authored-By: Brandon Oxendine --- src/components/PatchActivityItem.svelte | 11 +- src/components/PatchMetadata.svelte | 138 +++++++++++++++++++++--- src/components/Revision.svelte | 11 +- src/lib/utils.ts | 15 +++ src/views/repo/Patch.svelte | 4 +- 5 files changed, 159 insertions(+), 20 deletions(-) diff --git a/src/components/PatchActivityItem.svelte b/src/components/PatchActivityItem.svelte index 47a134590..a49057c1f 100644 --- a/src/components/PatchActivityItem.svelte +++ b/src/components/PatchActivityItem.svelte @@ -257,6 +257,11 @@ .merge-badge :global(*) { color: inherit; } + .merge-target { + display: inline-flex; + align-items: center; + gap: 0.25rem; + } .copy-link { display: inline-flex; align-items: center; @@ -572,7 +577,11 @@
merged patch {#if targetBranch} - into {targetBranch} + into + + + {targetBranch} + {/if}
diff --git a/src/components/PatchMetadata.svelte b/src/components/PatchMetadata.svelte index 0e2a5c6a7..9c6676f70 100644 --- a/src/components/PatchMetadata.svelte +++ b/src/components/PatchMetadata.svelte @@ -6,6 +6,7 @@ import type { Config } from "@bindings/config/Config"; import type { Stats } from "@bindings/diff/Stats"; import type { RepoInfo } from "@bindings/repo/RepoInfo"; + import type { RepoRefs } from "@bindings/repo/RepoRefs"; import debounce from "lodash/debounce"; @@ -19,12 +20,14 @@ summaryTitle, } from "@app/lib/reviewSummary"; import * as roles from "@app/lib/roles"; - import { push } from "@app/lib/router"; + import { push, routeToPath } from "@app/lib/router"; import { authorForNodeId, + defaultBranch, formatOid, pluralize, publicKeyFromDid, + unqualifyBranch, verdictIcon, } from "@app/lib/utils"; @@ -149,6 +152,58 @@ await loadPatch(); } } + + const targetBranch = $derived( + patch.targetBranch === undefined + ? undefined + : unqualifyBranch(patch.targetBranch), + ); + const targetBranchCaption = $derived( + `This patch merges into ${targetBranch}`, + ); + + // A patch's target is not validated when it is opened, so it can name a + // branch the source view cannot resolve. The default branch is canonical by + // definition; any other target needs the canonical ref list, which is + // expensive enough to load after render. An unresolved target renders + // unlinked — a missing link beats one that errors. + const targetIsDefaultBranch = $derived( + targetBranch !== undefined && targetBranch === defaultBranch(repo), + ); + + let canonicalBranches: Record | undefined = $state(); + let canonicalBranchesRid: string | undefined; + + $effect(() => { + if (targetBranch === undefined || targetIsDefaultBranch) { + return; + } + const requested = repo.rid; + if (canonicalBranchesRid === requested) { + return; + } + canonicalBranchesRid = requested; + canonicalBranches = undefined; + void invoke("list_repo_refs", { rid: requested }) + .then(refs => { + if (canonicalBranchesRid === requested) { + canonicalBranches = refs.canonical.branches; + } + }) + .catch(error => { + if (canonicalBranchesRid === requested) { + canonicalBranchesRid = undefined; + } + console.error("Failed to load repo refs", error); + }); + }); + + const targetBranchBrowsable = $derived( + targetIsDefaultBranch || + (targetBranch !== undefined && + canonicalBranches !== undefined && + targetBranch in canonicalBranches), + );