Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596<script lang="ts"> import Star from "$icon/star"; import { getAuth } from "$lib/auth.svelte"; import { createStar, deleteStar } from "$lib/api/graph"; import Button from "$lib/components/ui/Button.svelte"; import { getProfileCounts } from "$lib/components/profile/counts.svelte"; import { createOptimisticRelation, createOptimisticCount } from "$lib/optimistic.svelte";
interface Props { repoDid: string; repoOwnerHandle: string; repoName: string; initialCount?: number; initialRkey?: string | null; }
let { repoDid, repoOwnerHandle, repoName, initialCount, initialRkey }: Props = $props();
const auth = getAuth(); const profileCounts = getProfileCounts(); const signedIn = $derived(Boolean(auth.currentDid)); const relation = createOptimisticRelation({ key: () => `${auth.currentDid ?? ""}:${repoDid}`, loadedRkey: () => initialRkey }); const starCount = createOptimisticCount({ key: () => repoDid, loaded: () => initialCount });
let busy = $state(false); const starred = $derived(relation.active); const failed = $derived(relation.failed || starCount.failed);
const toggle = async () => { const agent = auth.agent; if (!agent || busy || !relation.known || !repoDid) return; busy = true; relation.resetFailure(); starCount.resetFailure(); try { if (relation.active && relation.rkey) { await deleteStar(agent, relation.rkey); relation.deleted(); starCount.adjust(-1); profileCounts?.adjust(agent.sub, "stars", -1); } else { const rkey = await createStar(agent, repoDid); relation.created(rkey); starCount.adjust(1); profileCounts?.adjust(agent.sub, "stars", 1); } } catch { relation.fail(); starCount.fail(); } finally { busy = false; } };</script>
{#if signedIn && repoDid} <div class="flex flex-col items-end"> <div class="inline-flex max-h-8 items-stretch divide-x divide-border-default overflow-clip rounded border border-border-default" > <Button variant="default" size="sm" class="min-h-7.5 flex-1 rounded-none border-0 before:rounded-none before:rounded-l-sm" loading={busy} disabled={!relation.known} onclick={toggle} > <Star class={`size-4 shrink-0 ${starred ? "[&_path]:fill-[currentColor]" : ""}`} aria-hidden="true" /> <span>{starred ? "Unstar" : "Star"}</span> </Button> <Button href={`/${repoOwnerHandle}/${repoName}/stars`} variant="ghost" size="sm" class="min-h-7.5 rounded-none" title="Starred by" > {starCount.value} </Button> </div> {#if failed} <p class="mt-1 text-xs text-foreground-danger">Something went wrong. Try again.</p> {/if} </div>{/if}