your personal website on atproto - mirror blento.app
24
fork

Configure Feed

Select the types of activity you want to include in your feed.

at button 114 lines 3.2 kB view raw
1<script lang="ts"> 2 import { onMount } from 'svelte'; 3 import Icon from './Icon.svelte'; 4 import { 5 getAdditionalUserData, 6 getDidContext, 7 getHandleContext, 8 getIsMobile 9 } from '$lib/website/context'; 10 import type { ContentComponentProps } from '../types'; 11 import { RelativeTime } from '@foxui/time'; 12 import { Badge } from '@foxui/core'; 13 import { CardDefinitionsByType } from '..'; 14 import { browser } from '$app/environment'; 15 16 let { item = $bindable() }: ContentComponentProps = $props(); 17 18 let isMobile = getIsMobile(); 19 20 let isLoaded = $state(false); 21 22 const data = getAdditionalUserData(); 23 24 let latestLivestream = $state( 25 data[item.cardType] as 26 | { 27 createdAt: string; 28 title: string; 29 thumb?: string; 30 href: string; 31 online?: boolean; 32 } 33 | undefined 34 ); 35 36 let did = getDidContext(); 37 let handle = getHandleContext(); 38 39 onMount(async () => { 40 if (!latestLivestream) { 41 latestLivestream = (await CardDefinitionsByType[item.cardType]?.loadData?.([], { 42 did, 43 handle 44 })) as 45 | { 46 createdAt: string; 47 title: string; 48 thumb?: string; 49 href: string; 50 online?: boolean; 51 } 52 | undefined; 53 54 data[item.cardType] = latestLivestream; 55 56 isLoaded = true; 57 } 58 }); 59</script> 60 61<div class="h-full overflow-y-scroll p-4"> 62 {#if latestLivestream} 63 <div class="flex min-h-full flex-col justify-between"> 64 <div> 65 <div class="mb-4 flex items-center gap-2"> 66 <Icon class="size-6" /> 67 <div class="font-semibold">Latest Livestream</div> 68 </div> 69 70 <div class="mb-2 flex items-center gap-2"> 71 <div class="text-xs font-medium"> 72 started <RelativeTime date={new Date(latestLivestream.createdAt)} locale="en-US" /> ago 73 </div> 74 {#if latestLivestream.online === true} 75 <Badge size="sm"> 76 <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> 77 <circle cx="50" cy="50" r="30" fill="currentColor" /> 78 </svg> 79 80 <span class="accent:text-base-900">live</span></Badge 81 > 82 {:else if latestLivestream.online === false} 83 <Badge size="sm" class="accent:text-base-900">ended</Badge> 84 {:else} 85 <div class="h-5.5"></div> 86 {/if} 87 </div> 88 89 <a href={latestLivestream?.href} target="_blank" rel="noopener noreferrer"> 90 <div 91 class="text-accent-700 dark:text-accent-300 accent:text-accent-950 hover:accent:text-accent-900 hover:text-accent-600 dark:hover:text-accent-400 text-xl font-semibold transition-colors duration-150" 92 > 93 {latestLivestream?.title} 94 </div> 95 </a> 96 </div> 97 98 {#if browser && ((isMobile() && item.mobileH >= 7) || (!isMobile() && item.h >= 4)) && latestLivestream?.thumb} 99 <a href={latestLivestream?.href} target="_blank" rel="noopener noreferrer"> 100 <img 101 class="my-4 max-h-32 w-full rounded-xl object-cover" 102 src={latestLivestream?.thumb} 103 alt="" 104 /> 105 <span class="sr-only">open livestream</span> 106 </a> 107 {/if} 108 </div> 109 {:else if isLoaded} 110 <div class="flex h-full w-full items-center justify-center">No latest stream found!</div> 111 {:else} 112 <div class="flex h-full w-full items-center justify-center">Looking for the latest stream</div> 113 {/if} 114</div>