This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / profile / tabs / StarredTab.svelte
2.1 kB 74 lines
1<script lang="ts"> 2 import { untrack } from "svelte"; 3 import { resolve } from "$app/paths"; 4 import { getAuth } from "$lib/auth.svelte"; 5 import { createBobbinClient } from "$lib/api/client"; 6 import { IdentityCache } from "$lib/api/identity"; 7 import { fetchStarredPage } from "../pages"; 8 import RepoCard from "$lib/components/repo/RepoCard.svelte"; 9 import Card from "$lib/components/ui/Card.svelte"; 10 import Section from "$lib/components/ui/Section.svelte"; 11 import LoadMore from "$lib/components/ui/LoadMore.svelte"; 12 import type { StarData } from "../types"; 13 14 interface Props { 15 initial: StarData[]; 16 cursor?: string; 17 did: string; 18 } 19 20 let { initial, cursor: initialCursor, did }: Props = $props(); 21 22 const auth = getAuth(); 23 24 let extra = $state<StarData[]>([]); 25 let cursor = $state(untrack(() => initialCursor)); 26 let loading = $state(false); 27 let failed = $state(false); 28 // shared across pages so repeat repo owners only resolve once 29 let identityCache: IdentityCache | undefined; 30 31 const stars = $derived([...initial, ...extra]); 32 33 const loadMore = async () => { 34 if (loading || !cursor) return; 35 loading = true; 36 failed = false; 37 try { 38 const ctx = createBobbinClient({ serviceUrl: auth.bobbinUrl }); 39 identityCache ??= new IdentityCache(ctx); 40 const next = await fetchStarredPage(ctx, { 41 did, 42 viewerDid: auth.currentDid ?? undefined, 43 cursor, 44 cache: identityCache 45 }); 46 extra = [...extra, ...next.items]; 47 cursor = next.cursor; 48 } catch { 49 failed = true; 50 } finally { 51 loading = false; 52 } 53 }; 54</script> 55 56<Section title="Starred" empty={stars.length === 0} emptyMessage="No stars yet."> 57 {#each stars as star (star.uri)} 58 {#if star.kind === "repo"} 59 <RepoCard repo={star.repo} /> 60 {:else} 61 <Card shadow={false} class="flex items-center gap-2"> 62 <a 63 href={resolve(`/${star.ownerHandle}/strings/${star.rkey}` as "/")} 64 class="truncate font-bold text-foreground-default no-underline hover:underline" 65 > 66 {star.ownerHandle}/{star.rkey} 67 </a> 68 </Card> 69 {/if} 70 {/each} 71 {#if cursor} 72 <LoadMore {loading} {failed} onclick={loadMore} /> 73 {/if} 74</Section>