Thread viewer for Bluesky
1<script lang="ts">
2 import { api } from '../../api.js';
3 import { BlockedPost, DetachedQuotePost, MissingPost, Post } from '../../models/posts.js';
4 import { settings } from '../../models/settings.svelte.js';
5
6 import BlockedPostContent from './BlockedPostContent.svelte';
7 import MissingPostView from './MissingPostView.svelte';
8 import PostSubtreeLink from './PostSubtreeLink.svelte';
9 import ReferencedPostAuthorLink from './ReferencedPostAuthorLink.svelte';
10
11 type Props = {
12 reason: string;
13 post: BlockedPost | DetachedQuotePost;
14 placement: PostPlacement;
15 }
16
17 let { reason, post, placement }: Props = $props();
18
19 let biohazardEnabled = $derived(settings.biohazardsEnabled !== false);
20 let loading = $state(false);
21 let postNotFound = $state(false);
22 let reloadedPost: Post | undefined = $state();
23
24 async function loadPost(e: Event) {
25 e.preventDefault();
26 loading = true;
27
28 let result = await api.reloadBlockedPost(post.uri);
29
30 if (result) {
31 reloadedPost = result;
32 } else {
33 postNotFound = true;
34 }
35 }
36
37 function canShowLoadThreadLink(reloadedPost: Post) {
38 let viewerInfo = reloadedPost.author.viewer;
39
40 if (viewerInfo) {
41 // don't show the link if author is blocked/blocking us, since full thread won't load anyway
42 return !(viewerInfo.blockedBy || viewerInfo.blocking);
43 } else {
44 // in incognito mode there will be no author viewer info - but in this case we can always load the thread
45 return true;
46 }
47 }
48
49 function blockStatus() {
50 if (post instanceof DetachedQuotePost) {
51 return undefined;
52 } else if (post.blockedByUser) {
53 return "has blocked you";
54 } else if (post.blocksUser) {
55 return "you've blocked them";
56 } else {
57 return undefined;
58 }
59 }
60</script>
61
62{#if !postNotFound && !reloadedPost}
63 <p class="blocked-header">
64 <i class="fa-solid fa-ban"></i> <span>{reason}</span>
65
66 {#if biohazardEnabled}
67 <ReferencedPostAuthorLink {post} status={blockStatus()} />
68 {/if}
69 </p>
70
71 {#if biohazardEnabled}
72 <p class="load-post">
73 {#if !loading}
74 <a href="#" onclick={loadPost}>Load post…</a>
75 {:else}
76
77 {/if}
78 </p>
79 {/if}
80{:else if reloadedPost}
81 <p class="blocked-header">
82 <i class="fa-solid fa-ban"></i> <span>{reason}</span>
83
84 <ReferencedPostAuthorLink {post} status={blockStatus()} />
85
86 {#if canShowLoadThreadLink(reloadedPost)}
87 <span class="separator">•</span>
88
89 <PostSubtreeLink post={reloadedPost} title="Load thread" />
90 {/if}
91 </p>
92
93 <BlockedPostContent post={reloadedPost} {placement} />
94{:else}
95 <MissingPostView post={new MissingPost(post.data)} />
96{/if}