your personal website on atproto - mirror blento.app

add live indicator

Florian 0e180adb cbd77fb9

+42 -3
+42 -3
src/lib/cards/LivestreamCard/LivestreamCard.svelte
··· 7 7 import type { ContentComponentProps } from '../types'; 8 8 import { getImageBlobUrl } from '$lib/website/utils'; 9 9 import { RelativeTime } from '@foxui/time'; 10 + import { online } from 'svelte/reactivity/window'; 11 + import { Badge } from '@foxui/core'; 10 12 11 13 let { item = $bindable() }: ContentComponentProps = $props(); 12 14 ··· 22 24 title: string; 23 25 thumb?: string; 24 26 href: string; 27 + online?: boolean; 25 28 } 26 29 | undefined = $state(); 27 30 ··· 38 41 createdAt: latest.value.createdAt, 39 42 title: latest.value.title as string, 40 43 thumb: getImageBlobUrl({ link: latest.value.thumb?.ref.$link, did }), 41 - href: latest.value.canonicalUrl || latest.value.url 44 + href: latest.value.canonicalUrl || latest.value.url, 45 + online: undefined 42 46 }; 43 47 } 44 48 49 + if (latestLivestream) { 50 + try { 51 + const segmentsResponse = await fetch( 52 + 'https://stream.place/xrpc/place.stream.live.getSegments?userDID=' + 53 + encodeURIComponent(did) 54 + ); 55 + const segments = await segmentsResponse.json(); 56 + 57 + const lastSegment = segments.segments[0]; 58 + const startTime = new Date(lastSegment.record.startTime).getTime(); 59 + 60 + const FIVE_MINUTES = 5 * 60 * 1000; 61 + const now = Date.now(); 62 + 63 + latestLivestream.online = now - startTime <= FIVE_MINUTES; 64 + } catch (error) { 65 + console.error(error); 66 + } 67 + } 68 + 45 69 isLoaded = true; 46 70 }); 47 71 </script> ··· 55 79 <div class="font-semibold">Latest Livestream</div> 56 80 </div> 57 81 58 - <div class="mb-2 text-xs font-medium"> 59 - started <RelativeTime date={new Date(latestLivestream.createdAt)} locale="en-US" /> ago 82 + <div class="mb-2 flex items-center gap-2"> 83 + <div class="text-xs font-medium"> 84 + started <RelativeTime date={new Date(latestLivestream.createdAt)} locale="en-US" /> ago 85 + </div> 86 + {#if latestLivestream.online === true} 87 + <Badge size="sm"> 88 + <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> 89 + <circle cx="50" cy="50" r="30" fill="currentColor" /> 90 + </svg> 91 + 92 + live</Badge 93 + > 94 + {:else if latestLivestream.online === false} 95 + <Badge size="sm">ended</Badge> 96 + {:else} 97 + <div class="h-[22px]"></div> 98 + {/if} 60 99 </div> 61 100 62 101 <a href={latestLivestream?.href} target="_blank" rel="noopener noreferrer">