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