~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
130 lines · 4.1 KB Raw History
<script lang="ts">
	import type { CheckView, CommitView, LanguageView } from '#lib/lexicons/dev/knotless/defs.ts';
	import type { Snippet } from 'svelte';
	import type * as getTree from '#lib/lexicons/dev/knotless/getTree.ts';
	import type { LastCommits } from '#lib/data.ts';
	import {
		age,
		heat,
		number,
		plural,
		repoHref,
		size,
		subject,
		urlPath,
		whenCommitted
	} from '#lib/format.ts';
	import CheckMark from '#lib/molecules/CheckMark.svelte';
	import CommitAuthor from '#lib/molecules/CommitAuthor.svelte';
	import LangEdge from '#lib/molecules/LangEdge.svelte';
	import Icon from '#lib/atoms/Icon.svelte';
	import Sha from '#lib/atoms/Sha.svelte';
	import Time from '#lib/atoms/Time.svelte';
	/**
	 * A directory, in one panel: edged by the `languages` it is written in,
	 * then `bar` (the revision and the ways to take it), its latest commit and
	 * how that commit's `checks` stand, then its entries, each with the commit
	 * that last changed it once `changes` has them.
	 */
	let {
		authority,
		name,
		rev,
		path,
		last,
		checks = [],
		entries,
		changes = null,
		languages = [],
		bar
	}: {
		authority: string;
		name: string;
		rev: string;
		path: string;
		last?: CommitView;
		checks?: CheckView[];
		entries: getTree.Entry[];
		changes?: LastCommits | Promise<LastCommits>;
		languages?: LanguageView[];
		bar?: Snippet;
	} = $props();
	const href = (tail: string) => repoHref(authority, name, tail);
	const prefix = $derived(path ? `${path}/` : '');
	const history = $derived(href(`/commits/${urlPath(rev)}/${urlPath(path)}`).replace(/\/$/, ''));
	/** At the root, once `changes` has it, how many commits its history holds. */
	const counted = (changes: LastCommits) => changes?.commitCount;
	/** The commit that last changed the entry `entry`, among `changes`. */
	const changed = (changes: LastCommits, entry: string): CommitView | undefined => {
		const sha = changes?.entries.find((e) => e.name === entry)?.sha;
		return changes?.commits.find((c) => c.sha === sha);
	};
</script>

<div class="box code-panel">
	{#if languages.length}<LangEdge {languages} />{:else}<div
			class="lang-edge"
			aria-hidden="true"
		></div>{/if}
	{#if bar}<div class="boxhead panel-bar">{@render bar()}</div>{/if}
	{#if last}
		<div class="boxhead last-head">
			<CommitAuthor commit={last} />
			<a class="grow clip mute" href={href(`/commit/${last.sha}`)}>{subject(last.message)}</a>
			<CheckMark {checks} />
			<Sha sha={last.sha} href={href(`/commit/${last.sha}`)} />
			<span class="mute hide-sm"><Time at={whenCommitted(last)} show={age} /></span>
			{#await changes}
				<a class="btn quiet history" href={history} title="History" aria-label="History"
					><Icon name="history" /><span class="words">History</span></a
				>
			{:then found}
				{@const n = counted(found)}
				{#if n === undefined}
					<a class="btn quiet history" href={history} title="History" aria-label="History"
						><Icon name="history" /><span class="words">History</span></a
					>
				{:else}
					<a
						class="btn quiet history"
						href={history}
						title={plural(n, 'commit', 'commits')}
						aria-label={plural(n, 'commit', 'commits')}
						><Icon name="history" /><span class="words"
							><b>{number(n)}</b>{` ${n === 1 ? 'commit' : 'commits'}`}</span
						></a
					>
				{/if}
			{/await}
		</div>
	{/if}
	<ul class="list files">
		{#each entries as e (e.name)}
			{@const tree = e.kind === 'tree'}
			<li class={tree ? 'dir' : ''}>
				<Icon name={tree ? 'dir' : 'file'} />
				<a
					class="name clip"
					href={href(`/${tree ? 'tree' : 'blob'}/${urlPath(rev)}/${urlPath(prefix + e.name)}`)}
					>{e.name}</a
				>
				{#await changes}
					<span class="grow" data-loading></span>
				{:then found}
					{@const c = changed(found, e.name)}
					{#if c}
						<a class="grow clip subject hide-sm" href={href(`/commit/${c.sha}`)}
							>{subject(c.message)}</a
						>
						<span class="when hide-sm" data-heat={heat(whenCommitted(c))}
							><Time at={whenCommitted(c)} show={age} /></span
						>
					{:else}
						<span class="grow"></span>
					{/if}
				{/await}
				<span class="size">{e.size === undefined ? '' : size(e.size)}</span>
			</li>
		{/each}
	</ul>
</div>