johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<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>