This repository has no description
1<script lang="ts">
2 import { untrack } from "svelte";
3 import { getAuth } from "$lib/auth.svelte";
4 import { createBobbinClient } from "$lib/api/client";
5 import { IdentityCache } from "$lib/api/identity";
6 import FollowCard from "../FollowCard.svelte";
7 import Section from "$lib/components/ui/Section.svelte";
8 import Pagination from "$lib/components/ui/Pagination.svelte";
9 import Error from "$lib/components/ui/Error.svelte";
10 import { createCursorPager, pageCount } from "../pagination.svelte";
11 import { PROFILE_PAGE_LIMIT, fetchPeoplePage } from "../pages";
12 import type { PersonData } from "../types";
13
14 interface Props {
15 initial: PersonData[];
16 cursor?: string;
17 total: number;
18 did: string;
19 direction: "followers" | "following";
20 title: string;
21 emptyMessage: string;
22 }
23
24 let {
25 initial,
26 cursor: initialCursor,
27 total,
28 did,
29 direction,
30 title,
31 emptyMessage
32 }: Props = $props();
33
34 const auth = getAuth();
35
36 // shared across pages so repeat dids only resolve once
37 let identityCache: IdentityCache | undefined;
38 const pager = createCursorPager(
39 { items: untrack(() => initial), cursor: untrack(() => initialCursor) },
40 (cursor) => {
41 const ctx = createBobbinClient({ serviceUrl: auth.bobbinUrl });
42 identityCache ??= new IdentityCache(ctx);
43 return fetchPeoplePage(ctx, {
44 did,
45 viewerDid: auth.currentDid ?? undefined,
46 direction,
47 cursor,
48 cache: identityCache
49 });
50 }
51 );
52 const people = $derived(pager.items);
53 const pages = $derived(pageCount(total, PROFILE_PAGE_LIMIT));
54</script>
55
56<Section {title} empty={people.length === 0} {emptyMessage} listClass="flex flex-col gap-8">
57 {#each people as person (person.did)}
58 <FollowCard {person} />
59 {/each}
60 {#snippet footer()}
61 {#if pages > 1}
62 <div class="mt-4 flex justify-center">
63 <Pagination
64 page={pager.state.page}
65 total={pages}
66 labels
67 disabled={pager.state.kind === "loading"}
68 onchange={pager.select}
69 class="gap-5"
70 />
71 </div>
72 {/if}
73 {#if pager.state.kind === "failed"}
74 <Error label="couldn't load that page. try again." class="mt-2" />
75 {/if}
76 {/snippet}
77</Section>