diff --git a/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte b/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte index ee2413974..3a331e262 100644 --- a/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte +++ b/web/src/routes/[handle]/[repo]/pulls/[aturi]/[version]/[[range]]/PullViewPage.svelte @@ -4,6 +4,8 @@ import { now as tidNow } from "@atcute/tid"; import BellPlus from "$icon/bell-plus"; import BellMinus from "$icon/bell-minus"; + import ChevronDown from "$icon/chevron-down"; + import ChevronRight from "$icon/chevron-right"; import IterationCcw from "$icon/iteration-ccw"; import PanelRightClose from "$icon/panel-right-close"; import MessagesSquare from "$icon/messages-square"; @@ -57,6 +59,7 @@ import PullCommitListDiff from "$lib/components/repo/pulls/PullCommitListDiff.svelte"; import TicketInfoBar from "$lib/components/repo/tickets/TicketInfoBar.svelte"; import type { PageData } from "./$types"; + import Separator from "$lib/components/ui/Separator.svelte"; type PullViewData = PageData & Exclude, { redirectTo: string }> & { @@ -181,6 +184,24 @@ }); }); + const conflictLabels: Record = { + "content conflict": "Edited", + "modify/delete conflict": "Edited & deleted", + "add/add conflict": "Added", + "rename conflict": "Renamed" + }; + + const conflictGroups = $derived.by(() => { + const groups: { label: string; filenames: string[] }[] = []; + for (const conflict of check.data?.conflicts ?? []) { + const label = conflictLabels[conflict.reason] ?? conflict.reason; + const group = groups.find((candidate) => candidate.label === label); + if (group) group.filenames.push(conflict.filename); + else groups.push({ label, filenames: [conflict.filename] }); + } + return groups; + }); + const short = (hash: string) => hash.slice(0, 8); // the at-uri sits outside `resolve`, which would drop the empty segment in `at://` @@ -280,6 +301,9 @@ const diff = createLoad(() => loadDiff(diffDeps, diffSpec)); + const conflictAnchor = (filename: string) => + diff.data?.files.some((file) => file.name === filename) ? `#file-${filename}` : undefined; + let discussionOpen = $state(true); let discussion = $state(); let discussionWidth = $state(0); @@ -643,18 +667,58 @@ style={discussionWidth ? `width: ${discussionWidth}px` : ""} class="fixed right-0 bottom-0 w-[max(20vw,21rem)] space-y-2 border-l border-border-default bg-background-default p-2" > + {#if check.data?.conflicts} +
+ + + + {check.data?.conflicts.length} + +
+ {#each conflictGroups as group (group.label)} + {group.label} +
+ {#each group.filenames as filename (filename)} + {@const anchor = conflictAnchor(filename)} + + {filename} + + {/each} +
+ {/each} +
+
+ + {/if} + -
- {#each check.data?.conflicts as conflict (conflict.filename)} -

{conflict.filename} - {conflict.reason}

- {/each} -
-