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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
51 lines · 1.7 KB Raw History
<script lang="ts">
	import type { RepoViewDetailed } from '#lib/lexicons/dev/knotless/defs.ts';
	import type * as starRepo from '#lib/lexicons/dev/knotless/starRepo.ts';
	import type * as unstarRepo from '#lib/lexicons/dev/knotless/unstarRepo.ts';
	import { call } from '#lib/data.ts';
	import { LOGIN } from '#lib/login.ts';
	import Icon from '#lib/atoms/Icon.svelte';
	/**
	 * How many have starred `repo`, and starring it as whoever is `in`: for
	 * anyone else, the way to log in first.
	 */
	let { repo, in: logged }: { repo: RepoViewDetailed; in: boolean } = $props();
	let star = $derived(repo.viewer?.star);
	let count = $derived(repo.starCount ?? 0);
	let busy = $state(false);
	// The count as a few characters, 1.2K or 3M; its title keeps every digit.
	const short = new Intl.NumberFormat('en', { notation: 'compact' });
	async function toggle() {
		busy = true;
		const input = { repo: repo.uri };
		const nsid = star ? 'dev.knotless.unstarRepo' : 'dev.knotless.starRepo';
		const state = await call<typeof starRepo.main | typeof unstarRepo.main>(nsid, input).catch(
			() => null
		);
		if (state) {
			star = state.star;
			count = state.starCount;
		}
		busy = false;
	}
</script>

<div class="star counted">
	{#if logged}
		<button
			class="btn"
			type="button"
			aria-pressed={!!star}
			disabled={busy}
			aria-busy={busy}
			onclick={toggle}
			><Icon name={star ? 'starred' : 'star'} /><span class="word">{star ? 'Starred' : 'Star'}</span
			></button
		>
	{:else}
		<button class="btn" type="button" popovertarget={LOGIN}
			><Icon name="star" /><span class="word">Star</span></button
		>
	{/if}
	<span class="count" title="{count} stars">{short.format(count)}</span>
</div>