pds dash for shimaenaga.veryroundbird.house (based off of pds.witchcraft.systems)
at main 4.5 kB view raw
1<script lang="ts"> 2 import { Post } from "./pdsfetch"; 3 import { Config } from "../../config"; 4 import { onMount } from "svelte"; 5 import moment from "moment"; 6 7 let { post }: { post: Post } = $props(); 8 9 // State for image carousel 10 let currentImageIndex = $state(0); 11 12 // Functions to navigate carousel 13 function nextImage() { 14 if (post.imagesCid && currentImageIndex < post.imagesCid.length - 1) { 15 currentImageIndex++; 16 } 17 } 18 19 function prevImage() { 20 if (currentImageIndex > 0) { 21 currentImageIndex--; 22 } 23 } 24 25 // Function to preload an image 26 function preloadImage(index: number): void { 27 if (!post.imagesCid || index < 0 || index >= post.imagesCid.length) return; 28 29 const img = new Image(); 30 img.src = `${Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did=${post.authorDid}&cid=${post.imagesCid[index]}`; 31 } 32 33 // Preload adjacent images when current index changes 34 $effect(() => { 35 if (post.imagesCid && post.imagesCid.length > 1) { 36 // Preload next image if available 37 if (currentImageIndex < post.imagesCid.length - 1) { 38 preloadImage(currentImageIndex + 1); 39 } 40 41 // Preload previous image if available 42 if (currentImageIndex > 0) { 43 preloadImage(currentImageIndex - 1); 44 } 45 } 46 }); 47 48 // Initial preload of images 49 onMount(() => { 50 if (post.imagesCid && post.imagesCid.length > 1) { 51 // Preload the next image if it exists 52 if (post.imagesCid.length > 1) { 53 preloadImage(1); 54 } 55 } 56 }); 57</script> 58 59<div class="postContainer"> 60 <div class="postHeader"> 61 {#if post.authorAvatarCid} 62 <img 63 class="avatar" 64 src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.authorAvatarCid}" 65 alt="avatar of {post.displayName}" 66 /> 67 {/if} 68 <div class="headerText"> 69 <a class="displayName" href="{Config.FRONTEND_URL}/profile/{post.authorDid}" 70 >{post.displayName}</a 71 > 72 <p class="handle"> 73 <a href="{Config.FRONTEND_URL}/profile/{post.authorHandle}" 74 >@{post.authorHandle}</a 75 > 76 77 <a 78 class="postLink" 79 href="{Config.FRONTEND_URL}/profile/{post.authorDid}/post/{post.recordName}" 80 >{moment(post.timenotstamp).isBefore(moment().subtract(1, "month")) 81 ? moment(post.timenotstamp).format("MMM D, YYYY") 82 : moment(post.timenotstamp).fromNow()}</a 83 > 84 </p> 85 </div> 86 </div> 87 <div class="postContent"> 88 {#if post.replyingUri} 89 <a 90 class="replyingText" 91 href="{Config.FRONTEND_URL}/profile/{post.replyingUri.repo}/post/{post 92 .replyingUri.rkey}">replying to {post.replyingUri.repo}</a 93 > 94 {/if} 95 {#if post.quotingUri} 96 <a 97 class="quotingText" 98 href="{Config.FRONTEND_URL}/profile/{post.quotingUri.repo}/post/{post 99 .quotingUri.rkey}">quoting {post.quotingUri.repo}</a 100 > 101 {/if} 102 <div class="postText">{post.text}</div> 103 {#if post.imagesCid && post.imagesCid.length > 0} 104 <div id="carouselContainer"> 105 <img 106 class="embedImages" 107 alt="Post Image {currentImageIndex + 1} of {post.imagesCid.length}" 108 src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post 109 .imagesCid[currentImageIndex]}" 110 /> 111 112 {#if post.imagesCid.length > 1} 113 <div class="carouselControls"> 114 <button 115 id="prevBtn" 116 onclick={prevImage} 117 disabled={currentImageIndex === 0}></button 118 > 119 <div class="carouselIndicators"> 120 {#each post.imagesCid as _, i} 121 <div 122 class="indicator {i === currentImageIndex ? 'active' : ''}" 123 ></div> 124 {/each} 125 </div> 126 <button 127 class="nextBtn" 128 onclick={nextImage} 129 disabled={currentImageIndex === post.imagesCid.length - 1} 130 ></button 131 > 132 </div> 133 {/if} 134 </div> 135 {/if} 136 {#if post.videosLinkCid} 137 <!-- svelte-ignore a11y_media_has_caption --> 138 <video 139 class="embedVideo" 140 src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}" 141 controls 142 ></video> 143 {/if} 144 {#if post.gifLink} 145 <img 146 class="embedVideo" 147 src="{post.gifLink}" 148 alt="Post GIF" 149 /> 150 {/if} 151 </div> 152</div> 153 154<style> 155 156</style>