Thread viewer for Bluesky
at master 109 lines 3.0 kB view raw
1<script lang="ts"> 2 import { api } from '../../api.js'; 3 import { getPostContext } from '../posts/PostComponent.svelte'; 4 import { BasePost, Post, MissingPost } from '../../models/posts.js'; 5 import { InlineRecordEmbed, InlineRecordWithMediaEmbed } from '../../models/embeds.js'; 6 import { ATProtoRecord, FeedGeneratorRecord, StarterPackRecord, UserListRecord } from '../../models/records.js'; 7 import { atURI } from '../../utils.js'; 8 9 import FeedGeneratorView from '../embeds/FeedGeneratorView.svelte'; 10 import PostWrapper from '../posts/PostWrapper.svelte'; 11 import StarterPackView from '../embeds/StarterPackView.svelte'; 12 import UserListView from '../embeds/UserListView.svelte'; 13 14 let { record }: { record: ATProtoRecord } = $props(); 15 let { post } = getPostContext(); 16 17 async function loadQuotedRecord(): Promise<ATProtoRecord> { 18 let { collection } = atURI(record.uri); 19 20 if (collection == 'app.bsky.feed.post') { 21 let reloaded = await api.loadPostIfExists(record.uri); 22 23 if (reloaded) { 24 return new Post(reloaded); 25 } else { 26 return new MissingPost(post.data); 27 } 28 } else { 29 let reloadedPost = await api.loadPostIfExists(post.uri).then(x => x && new Post(x)); 30 let newEmbed = reloadedPost?.embed; 31 32 if (newEmbed instanceof InlineRecordEmbed || newEmbed instanceof InlineRecordWithMediaEmbed) { 33 return newEmbed.record; 34 } else { 35 return new MissingPost(record); 36 } 37 } 38 } 39</script> 40 41{#if record.constructor === ATProtoRecord && !record.type} 42 {#await loadQuotedRecord()} 43 <div class="quote-embed"> 44 <p class="post placeholder">Loading quoted post...</p> 45 </div> 46 {:then record} 47 {@render quoteContent(record)} 48 {:catch} 49 <div class="quote-embed"> 50 <p class="post placeholder">Error loading quoted post</p> 51 </div> 52 {/await} 53{:else} 54 {@render quoteContent(record)} 55{/if} 56 57{#snippet quoteContent(record: ATProtoRecord)} 58 {#if record instanceof BasePost} 59 <div class="quote-embed"> 60 <PostWrapper post={record} placement="quote" /> 61 </div> 62 63 {:else if record instanceof FeedGeneratorRecord} 64 <FeedGeneratorView feed={record} /> 65 66 {:else if record instanceof StarterPackRecord} 67 <StarterPackView starterPack={record} /> 68 69 {:else if record instanceof UserListRecord} 70 <UserListView list={record} /> 71 72 {:else} 73 <div class="quote-embed"> 74 <p>[{record.type}]</p> 75 </div> 76 {/if} 77{/snippet} 78 79<style> 80 .quote-embed { 81 border: 1px solid #ddd; 82 border-radius: 8px; 83 background-color: #fbfcfd; 84 margin-top: 25px; 85 margin-bottom: 15px; 86 margin-left: 0px; 87 max-width: 800px; 88 } 89 90 .quote-embed :global(.post) { 91 margin-top: 16px; 92 padding-left: 16px; 93 padding-right: 16px; 94 padding-bottom: 5px; 95 } 96 97 .placeholder { 98 font-style: italic; 99 font-size: 11pt; 100 color: #888; 101 } 102 103 @media (prefers-color-scheme: dark) { 104 .quote-embed { 105 background-color: #303030; 106 border-color: #606060; 107 } 108 } 109</style>