your personal website on atproto - mirror blento.app
at main 90 lines 2.3 kB view raw
1<script lang="ts"> 2 import { getDidContext } from '$lib/website/context'; 3 import { getBlobURL } from '$lib/atproto'; 4 import { onMount } from 'svelte'; 5 import type { ContentComponentProps } from '../types'; 6 7 let { item = $bindable() }: ContentComponentProps = $props(); 8 9 const did = getDidContext(); 10 11 let element: HTMLVideoElement | undefined = $state(); 12 13 onMount(async () => { 14 const el = element; 15 if (!el) return; 16 17 el.muted = true; 18 19 // If we already have an objectUrl (preview before upload), use it directly 20 if (item.cardData.objectUrl) { 21 el.src = item.cardData.objectUrl; 22 el.play().catch((e) => { 23 console.error('Video play error:', e); 24 }); 25 return; 26 } 27 28 // Fetch the video blob from the PDS 29 if (item.cardData.video?.video && typeof item.cardData.video.video === 'object') { 30 try { 31 const blobUrl = await getBlobURL({ did, blob: item.cardData.video.video }); 32 const res = await fetch(blobUrl); 33 if (!res.ok) throw new Error(res.statusText); 34 const blob = await res.blob(); 35 const url = URL.createObjectURL(blob); 36 el.src = url; 37 el.play().catch((e) => { 38 console.error('Video play error:', e); 39 }); 40 } catch (e) { 41 console.error('Failed to load video:', e); 42 } 43 } 44 }); 45</script> 46 47{#key item.cardData.video || item.cardData.objectUrl} 48 <video 49 bind:this={element} 50 muted 51 loop 52 autoplay 53 playsinline 54 class={[ 55 'absolute inset-0 h-full w-full object-cover opacity-100 transition-transform duration-300 ease-in-out', 56 item.cardData.href ? 'group-hover:scale-102' : '' 57 ]} 58 ></video> 59{/key} 60{#if item.cardData.href} 61 <a 62 href={item.cardData.href} 63 class="absolute inset-0 h-full w-full" 64 target="_blank" 65 rel="noopener noreferrer" 66 > 67 <span class="sr-only"> 68 {item.cardData.hrefText ?? 'Learn more'} 69 </span> 70 71 <div 72 class="bg-base-800/30 border-base-900/30 absolute top-2 right-2 rounded-full border p-1 text-white opacity-50 backdrop-blur-lg group-focus-within:opacity-100 group-hover:opacity-100" 73 > 74 <svg 75 xmlns="http://www.w3.org/2000/svg" 76 fill="none" 77 viewBox="0 0 24 24" 78 stroke-width="2.5" 79 stroke="currentColor" 80 class="size-4" 81 > 82 <path 83 stroke-linecap="round" 84 stroke-linejoin="round" 85 d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" 86 /> 87 </svg> 88 </div> 89 </a> 90{/if}