Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162<script lang="ts"> import CommitBodyToggle from "$lib/components/repo/CommitBodyToggle.svelte"; import CommitSignOff from "$lib/components/repo/CommitSignOff.svelte"; import DiffStatPill from "$lib/components/repo/DiffStatPill.svelte"; import MessageSquare from "$icon/message-square"; import { hasBodyBeyondSignOffs, signOffsFrom } from "$lib/api/repo"; import type { CommitStatuses } from "$lib/api/commitStatuses"; import ProfilePopover from "$lib/components/profile/ProfilePopover.svelte"; import Avatar from "$lib/components/ui/Avatar.svelte"; import TextSwap from "$lib/components/ui/TextSwap.svelte"; import PipelineWorkflows from "$lib/components/repo/pipelines/PipelineWorkflows.svelte"; import type { CommitSummary } from "$lib/components/repo/types";
interface Props { commit: CommitSummary; pipelineStatuses?: Promise<CommitStatuses>; showAvatar?: boolean; showChangeId?: boolean; ontoggleIds?: () => void; onclick?: (event: MouseEvent) => void; onpointerenter?: () => void; onpointerleave?: () => void; }
let { commit, pipelineStatuses, showAvatar = true, showChangeId = true, ontoggleIds, onclick, onpointerenter, onpointerleave }: Props = $props();
let expanded = $state(false);
// selecting the id to copy it ends in a click, which must not flip every row const flipIds = () => { if (window.getSelection()?.toString()) return; ontoggleIds?.(); };
// the browser only offers Copy when the click lands inside a selection, so take the id // for the reader and let the native menu open over it const selectId = (event: MouseEvent) => { const selection = window.getSelection(); if (!selection || selection.toString()) return; const range = document.createRange(); range.selectNodeContents(event.currentTarget as HTMLElement); selection.removeAllRanges(); selection.addRange(range); };
const signOffs = $derived(signOffsFrom(commit.body)); const hasBody = $derived(hasBodyBeyondSignOffs(commit.body)); const changeId = $derived(commit.changeId?.slice(0, 8)); const id = $derived(showChangeId && changeId ? changeId : commit.shortHash);</script>
<div role="none" {onpointerenter} {onpointerleave} class="relative grid min-h-10 flex-1 grid-cols-[minmax(0,1fr)] gap-x-xs px-sm sm:grid-cols-[5rem_minmax(0,1fr)_10rem]"> {#if onclick} <button type="button" class="absolute inset-x-0 top-0 h-10 cursor-pointer" aria-label="Show changes in {commit.shortHash}" {onclick} ></button> {/if} {#if ontoggleIds} <!-- a span, not a button: chromium refuses to select text inside a button, and the id has to be selectable to be copied --> <span role="button" tabindex="0" class="relative col-start-1 row-start-1 hidden h-10 w-fit cursor-pointer items-center typography-monospace-regular text-foreground-muted select-text sm:flex" title={showChangeId ? "Show commit hashes" : "Show change IDs"} onclick={flipIds} oncontextmenu={selectId} onkeydown={(event) => { if (event.key !== "Enter" && event.key !== " ") return; event.preventDefault(); ontoggleIds?.(); }} > <TextSwap value={id} /> </span> {:else} <span class="col-start-1 row-start-1 hidden h-10 items-center truncate typography-monospace-regular text-foreground-muted select-text sm:flex" > {id} </span> {/if} <div class="pointer-events-none relative col-start-1 row-start-1 flex h-10 min-w-0 items-center gap-xs sm:col-start-2" > {#if showAvatar} {#if commit.authorHandle && commit.authorDid} <ProfilePopover identifier={commit.authorDid}> <Avatar did={commit.authorDid} handle={commit.authorHandle} size="large" class="pointer-events-auto cursor-pointer" /> </ProfilePopover> {:else} <Avatar handle={commit.authorName} size="large" /> {/if} {/if} <span class="min-w-0 truncate">{commit.subject}</span> {#if signOffs.length > 0} <CommitSignOff {signOffs} class="pointer-events-auto" /> {/if} {#if hasBody} <CommitBodyToggle class="pointer-events-auto hidden sm:block" {expanded} onclick={() => (expanded = !expanded)} /> {/if} {#if pipelineStatuses} {#await pipelineStatuses then statuses} {#if statuses[commit.hash]} <div class="pointer-events-auto hidden shrink-0 sm:block"> <PipelineWorkflows ownerHandle="tangled.org" repoName="core" size="mini" variant="symbol" pipeline={statuses[commit.hash]} /> </div> {/if} {/await} {/if} </div> <div class="pointer-events-none relative col-start-3 row-start-1 hidden h-10 items-center justify-end gap-sm sm:flex" > {#if commit.commentCount} <div class="flex items-center gap-2xs text-foreground-muted"> <span>{commit.commentCount}</span> <MessageSquare class="size-3.5" /> </div> {/if} {#if commit.stat} <DiffStatPill stat={commit.stat} size="small" /> {/if} </div> {#if hasBody && expanded} <pre class="col-span-2 col-start-2 row-start-2 mb-xs hidden typography-monospace-regular whitespace-pre-wrap sm:block">{commit.body}</pre> {/if}</div>