Thread viewer for Bluesky
1<script lang="ts">
2 import { api, blueAPI } from '../api.js';
3 import { Post } from '../models/posts.js';
4 import { showError } from '../utils.js';
5 import * as paginator from '../utils/paginator.js';
6 import FeedPostParent from '../components/posts/FeedPostParent.svelte';
7 import MainLoader from '../components/MainLoader.svelte';
8 import PostComponent from '../components/posts/PostComponent.svelte';
9
10 let isLoading = false;
11 let cursor: string | undefined;
12 let finished = false;
13
14 let { postURL }: { postURL: string } = $props();
15
16 let posts: Post[] = $state([]);
17 let quoteCount: number | undefined = $state();
18 let loadingFailed = $state(false);
19
20 paginator.loadInPages(async () => {
21 if (isLoading || finished) { return }
22 isLoading = true;
23
24 try {
25 let data = await blueAPI.getQuotes(postURL, cursor);
26 let jsons = await api.loadPosts(data.posts);
27 let batch = jsons.map(j => new Post(j));
28
29 if (quoteCount === undefined) {
30 quoteCount = data.quoteCount;
31 }
32
33 posts.push(...batch);
34
35 isLoading = false;
36 cursor = data.cursor;
37
38 if (!cursor || posts.length == 0) {
39 finished = true;
40 }
41 } catch(error) {
42 console.log(error);
43 isLoading = false;
44 loadingFailed = true;
45 showError(error);
46 }
47 });
48</script>
49
50{#if quoteCount !== undefined}
51 <main class="quotes">
52 <header>
53 <h2>
54 {#if quoteCount > 1}
55 {quoteCount} quotes:
56 {:else if quoteCount == 1}
57 1 quote:
58 {:else}
59 No quotes found.
60 {/if}
61 </h2>
62 </header>
63
64 {#each posts as post (post.uri)}
65 <!-- note: posts here are loaded via getPosts, so they don't include full parent/thread info -->
66 {#if post.parentReference}
67 <FeedPostParent uri={post.parentReference.uri} />
68 {/if}
69
70 <PostComponent {post} placement="quotes" />
71 {/each}
72 </main>
73{:else if !loadingFailed}
74 <MainLoader />
75{/if}
76
77<style>
78 .quotes :global(p.back) {
79 padding-left: 10px;
80 }
81
82 .quotes :global(.post) {
83 padding-bottom: 5px;
84 }
85
86 .quotes :global(.post-quote .quote-embed) {
87 display: none;
88 }
89
90 .quotes :global(.post-quote p.stats) {
91 display: none;
92 }
93</style>