Thread viewer for Bluesky
1<script lang="ts">
2 import { api } from '../../api.js';
3 import { showBiohazardDialog } from '../Dialogs.svelte';
4 import { settings } from '../../models/settings.svelte.js';
5 import { parseThreadPost } from '../../models/posts.js';
6 import { linkToPostThread } from '../../router.js';
7 import { getPostContext } from './PostComponent.svelte';
8
9 type Props = {
10 onLoad: (posts: (AnyPost | null)[]) => void,
11 onError: (error: Error) => void
12 }
13
14 let { onLoad, onError }: Props = $props();
15 let { post } = getPostContext();
16 let loading = $state(false);
17
18 function onLinkClick(e: Event) {
19 e.preventDefault();
20
21 if (settings.biohazardsEnabled === true) {
22 loadHiddenReplies();
23 } else {
24 showBiohazardDialog(() => {
25 loadHiddenReplies();
26 });
27 }
28 }
29
30 async function loadHiddenReplies() {
31 loading = true;
32
33 try {
34 let repliesData = await api.loadHiddenReplies(post);
35 let replies = repliesData.map(x => x && parseThreadPost(x.thread, post.pageRoot, 1, post.absoluteLevel + 1));
36 loading = false;
37 onLoad(replies);
38 } catch (error) {
39 loading = false;
40 onError(error);
41 }
42 }
43</script>
44
45<p class="hidden-replies">
46 {#if !loading}
47 ☣️ <a href={linkToPostThread(post)} onclick={onLinkClick}>Load hidden replies…</a>
48 {:else}
49 <img class="loader" src="icons/sunny.png" alt="Loading...">
50 {/if}
51</p>
52
53<style>
54 .hidden-replies {
55 margin-top: 20px;
56 font-size: 11pt;
57 }
58
59 .hidden-replies a {
60 font-size: 12pt;
61 color: saddlebrown;
62 }
63</style>