Thread viewer for Bluesky
at master 93 lines 2.2 kB view raw
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>