your personal website on atproto - mirror blento.app
at improve-link-card 95 lines 3.0 kB view raw
1<script lang="ts"> 2 import Card from '../cards/Card/Card.svelte'; 3 import Profile from './Profile.svelte'; 4 import { 5 getDescription, 6 getHideProfileSection, 7 getProfilePosition, 8 getName, 9 sortItems 10 } from '../helper'; 11 import { innerWidth } from 'svelte/reactivity/window'; 12 import { setDidContext, setHandleContext, setIsMobile } from './context'; 13 import BaseCard from '../cards/BaseCard/BaseCard.svelte'; 14 import type { WebsiteData } from '$lib/types'; 15 import Context from './Context.svelte'; 16 import MadeWithBlento from './MadeWithBlento.svelte'; 17 import Head from './Head.svelte'; 18 import type { Did, Handle } from '@atcute/lexicons'; 19 import QRModalProvider from '$lib/components/qr/QRModalProvider.svelte'; 20 import EmptyState from './EmptyState.svelte'; 21 import FloatingEditButton from './FloatingEditButton.svelte'; 22 import { user } from '$lib/atproto'; 23 import { env } from '$env/dynamic/public'; 24 25 let { data }: { data: WebsiteData } = $props(); 26 27 // Check if floating edit button will be visible (to hide MadeWithBlento) 28 const isOwnPage = $derived(user.isLoggedIn && user.profile?.did === data.did); 29 const isBlento = $derived(!env.PUBLIC_IS_SELFHOSTED && data.handle === 'blento.app'); 30 const showFloatingButton = $derived( 31 isOwnPage || 32 (isBlento && !user.isInitializing && !user.isLoggedIn) || 33 (isBlento && user.isLoggedIn && user.profile?.handle !== data.handle) 34 ); 35 36 let isMobile = $derived((innerWidth.current ?? 1000) < 1024); 37 setIsMobile(() => isMobile); 38 39 // svelte-ignore state_referenced_locally 40 setDidContext(data.did as Did); 41 // svelte-ignore state_referenced_locally 42 setHandleContext(data.handle as Handle); 43 44 let maxHeight = $derived( 45 data.cards.reduce( 46 (max, item) => Math.max(max, isMobile ? item.mobileY + item.mobileH : item.y + item.h), 47 0 48 ) 49 ); 50 51 let container: HTMLDivElement | undefined = $state(); 52</script> 53 54<Head 55 favicon={data.profile.avatar ?? null} 56 title={getName(data)} 57 image={'/' + data.handle + '/og.png'} 58 description={getDescription(data)} 59/> 60 61<Context {data}> 62 <QRModalProvider /> 63 <div class="@container/wrapper relative w-full"> 64 {#if !getHideProfileSection(data)} 65 <Profile {data} hideBlento={showFloatingButton} /> 66 {/if} 67 68 <div 69 class={[ 70 'mx-auto max-w-lg', 71 !getHideProfileSection(data) && getProfilePosition(data) === 'side' 72 ? '@5xl/wrapper:grid @5xl/wrapper:max-w-7xl @5xl/wrapper:grid-cols-4' 73 : '@5xl/wrapper:max-w-4xl' 74 ]} 75 > 76 <div></div> 77 <div bind:this={container} class="@container/grid relative col-span-3 px-2 py-8 lg:px-8"> 78 {#if data.cards.length === 0} 79 <EmptyState {data} /> 80 {:else} 81 {#each data.cards.toSorted(sortItems) as item (item.id)} 82 <BaseCard {item}> 83 <Card {item} /> 84 </BaseCard> 85 {/each} 86 <div style="height: {(maxHeight / 8) * 100}cqw;"></div> 87 {/if} 88 </div> 89 </div> 90 91 <MadeWithBlento class="mx-auto block pb-8 text-center @5xl/wrapper:hidden" /> 92 </div> 93 94 <FloatingEditButton {data} /> 95</Context>