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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
175 lines · 6.1 KB Raw History
<script lang="ts" module>
	export type Kind = 'all' | 'sources' | 'forks' | 'shared';
	export type Order = 'pushed' | 'created' | 'name';
</script>

<script lang="ts">
	import type { RepoView } from '#lib/lexicons/dev/knotless/defs.ts';
	import type * as getActorActivity from '#lib/lexicons/dev/knotless/getActorActivity.ts';
	import { ago, date, repoHref } from '#lib/format.ts';
	import { RECENT, weekly } from '#lib/activity.ts';
	import Avatar from '#lib/atoms/Avatar.svelte';
	import Icon from '#lib/atoms/Icon.svelte';
	import Language from '#lib/atoms/Language.svelte';
	import PrivateTag from '#lib/atoms/PrivateTag.svelte';
	import Spark from '#lib/atoms/Spark.svelte';
	import Time from '#lib/atoms/Time.svelte';
	import FilterMenu from '#lib/molecules/FilterMenu.svelte';
	import type { Snippet } from 'svelte';
	import Empty from '#lib/molecules/Empty.svelte';
	/**
	 * All of an account's repositories, those whose name or description
	 * holds `q`, of `kind`, in `order`: each with what it is, the language
	 * it is mostly written in, when it was last pushed to or made, and,
	 * when `pushes` says, its pushes each week of the last few to `today`;
	 * or, as `shared`, those of others shared with it, by owner and name.
	 * The filters are links from `base`.
	 */
	let {
		repos,
		shared = [],
		pushes,
		today,
		q = '',
		kind = 'all',
		order = 'pushed',
		base,
		empty
	}: {
		repos: RepoView[];
		shared?: RepoView[];
		pushes: getActorActivity.RepoActivity[] | null;
		today: string;
		q?: string;
		kind?: Kind;
		order?: Order;
		base: string;
		empty: Snippet;
	} = $props();
	// Pushes are the account's own: none are counted for what is shared.
	const pushed = $derived(new Map(kind === 'shared' ? [] : (pushes ?? []).map((p) => [p.name, p])));
	const last = (r: RepoView) => pushed.get(r.name)?.pushedAt ?? r.createdAt;
	const listed = $derived(kind === 'shared' ? shared : repos);
	// What is shared has no pushes of the account's to sort by: newest first.
	const sort = $derived(kind === 'shared' && order === 'pushed' ? 'created' : order);
	const shown = $derived.by(() => {
		const words = q.trim().toLowerCase();
		const found = listed.filter(
			(r) =>
				(kind === 'all' || kind === 'shared' || (kind === 'forks') === Boolean(r.forkOf)) &&
				(!words || `${r.name} ${r.description ?? ''}`.toLowerCase().includes(words))
		);
		const by = {
			pushed: (a: RepoView, b: RepoView) => last(b).localeCompare(last(a)),
			created: (a: RepoView, b: RepoView) => b.createdAt.localeCompare(a.createdAt),
			name: (a: RepoView, b: RepoView) => a.name.localeCompare(b.name)
		}[sort];
		return found.sort(by);
	});
	const href = (to: { kind?: Kind; order?: Order; q?: string }) => {
		const k = to.kind ?? kind;
		const o = to.order ?? order;
		const words = to.q ?? q;
		const params = new URLSearchParams({ tab: 'repos' });
		if (words) params.set('q', words);
		if (k !== 'all') params.set('kind', k);
		if (o !== 'pushed') params.set('sort', o);
		return `${base}?${params}`;
	};
	const orders: [Order, string][] = [
		['pushed', 'Recently pushed'],
		['created', 'Newest'],
		['name', 'Name']
	];
	const sorts = $derived(
		orders
			.filter(([o]) => kind !== 'shared' || o !== 'pushed')
			.map(([o, name]) => ({ name, href: href({ order: o }), on: o === sort }))
	);
	const weeks = (name: string) =>
		weekly(pushed.get(name)?.days ?? [], today, RECENT, (d) => d.pushes);
</script>

<form class="query" role="search" action={base}>
	<Icon name="search" /><input type="hidden" name="tab" value="repos" /><input
		type="search"
		name="q"
		value={q}
		placeholder="Find a repository"
		aria-label="Find a repository"
	/>
	{#if kind !== 'all'}<input
			type="hidden"
			name="kind"
			value={kind}
		/>{/if}{#if order !== 'pushed'}<input type="hidden" name="sort" value={order} />{/if}
</form>
<div class="box items">
	<div class="boxhead" data-sveltekit-reset="false">
		<nav class="filter">
			<a href={href({ kind: 'all' })} aria-current={kind === 'all' ? 'page' : undefined}>All</a>
			<a href={href({ kind: 'sources' })} aria-current={kind === 'sources' ? 'page' : undefined}
				>Sources</a
			>
			<a href={href({ kind: 'forks' })} aria-current={kind === 'forks' ? 'page' : undefined}
				>Forks</a
			>
			{#if shared.length || kind === 'shared'}<a
					href={href({ kind: 'shared' })}
					aria-current={kind === 'shared' ? 'page' : undefined}>Shared</a
				>{/if}
		</nav>
		<div class="menus"><FilterMenu title="Sort" head="Sort by" options={sorts} /></div>
	</div>
	<ul class="list">
		{#each shown as r (`${r.owner.did}/${r.name}`)}
			{@const p = pushed.get(r.name)}
			<li>
				{#if kind === 'shared'}<Avatar
						name={r.owner.handle}
						size="lg"
						did={r.owner.did}
						src={r.owner.avatar}
					/>{/if}
				<div class="grow">
					<a class="title" href={repoHref(r.owner.handle, r.name)}
						>{#if kind === 'shared'}<span class="mute">{r.owner.handle}/</span>{/if}{r.name}</a
					>{#if r.private}{' '}<PrivateTag />{/if}
					<div class="meta">{r.description ?? 'No description'}</div>
					{#if r.forkOf}<div class="meta">
							<Icon name="fork" />Forked from
							<a href={repoHref(r.forkOf.handle, r.forkOf.name)}
								>{`${r.forkOf.handle}/${r.forkOf.name}`}</a
							>
						</div>{/if}
					<div class="meta">
						{#if r.language}<Language language={r.language} />{/if}{#if p}<span
								>{'Pushed '}<Time at={p.pushedAt} show={ago} /></span
							>{:else}<span>{'Created '}<Time at={r.createdAt} show={date} /></span>{/if}
					</div>
				</div>
				{#if pushes && kind !== 'shared'}<span class="hide-sm"
						><Spark
							values={weeks(r.name)}
							label="Pushes each week, the last {RECENT} weeks"
						/></span
					>{/if}
			</li>
		{:else}
			<li class="blank">
				{#if listed.length && q.trim()}
					<Empty title="No repositories match"><a href={href({ q: '' })}>Clear the search</a></Empty
					>
				{:else if listed.length}
					<Empty title={kind === 'forks' ? 'No forks yet' : 'No sources yet'}
						><a href={href({ kind: 'all' })}>See all repositories</a></Empty
					>
				{:else if kind === 'shared'}
					<Empty title="No repositories shared with you yet" />
				{:else}
					{@render empty()}
				{/if}
			</li>
		{/each}
	</ul>
</div>