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.4 kB 78 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 RepoCard from "$lib/components/repo/RepoCard.svelte"; 8 import Card from "$lib/components/ui/Card.svelte"; 9 import Section from "$lib/components/ui/Section.svelte"; 10 import Pagination from "$lib/components/ui/Pagination.svelte"; 11 import Error from "$lib/components/ui/Error.svelte"; 12 import { createCursorPager, pageCount } from "../pagination.svelte"; 13 import { PROFILE_PAGE_LIMIT, fetchStarredPage } from "../pages"; 14 import type { StarData } from "../types"; 15 16 interface Props { 17 initial: StarData[]; 18 cursor?: string; 19 total: number; 20 did: string; 21 } 22 23 let { initial, cursor: initialCursor, total, did }: Props = $props(); 24 25 const auth = getAuth(); 26 27 // shared across pages so repeat repo owners only resolve once 28 let identityCache: IdentityCache | undefined; 29 const pager = createCursorPager( 30 { items: untrack(() => initial), cursor: untrack(() => initialCursor) }, 31 (cursor) => { 32 const ctx = createBobbinClient({ serviceUrl: auth.bobbinUrl }); 33 identityCache ??= new IdentityCache(ctx); 34 return fetchStarredPage(ctx, { 35 did, 36 viewerDid: auth.currentDid ?? undefined, 37 cursor, 38 cache: identityCache 39 }); 40 } 41 ); 42 const stars = $derived(pager.items); 43 const pages = $derived(pageCount(total, PROFILE_PAGE_LIMIT)); 44</script> 45 46<Section title="Starred" empty={stars.length === 0} emptyMessage="No stars yet."> 47 {#each stars as star (star.uri)} 48 {#if star.kind === "repo"} 49 <RepoCard repo={star.repo} /> 50 {:else} 51 <Card shadow={false} class="flex items-center gap-2"> 52 <a 53 href={resolve(`/${star.ownerHandle}/strings/${star.rkey}` as "/")} 54 class="truncate font-bold text-foreground-default no-underline hover:underline" 55 > 56 {star.ownerHandle}/{star.rkey} 57 </a> 58 </Card> 59 {/if} 60 {/each} 61 {#snippet footer()} 62 {#if pages > 1} 63 <div class="mt-4 flex justify-center"> 64 <Pagination 65 page={pager.state.page} 66 total={pages} 67 labels 68 disabled={pager.state.kind === "loading"} 69 onchange={pager.select} 70 class="gap-5" 71 /> 72 </div> 73 {/if} 74 {#if pager.state.kind === "failed"} 75 <Error label="couldn't load that page. try again." class="mt-2" /> 76 {/if} 77 {/snippet} 78</Section>