your personal website on atproto - mirror
blento.app
1<script lang="ts">
2 import type { Item } from '$lib/types';
3 import { onMount } from 'svelte';
4 import {
5 getAdditionalUserData,
6 getDidContext,
7 getHandleContext,
8 getIsMobile
9 } from '$lib/website/context';
10 import { CardDefinitionsByType } from '../..';
11 import { getCDNImageBlobUrl, parseUri } from '$lib/atproto';
12
13 import { ImageMasonry } from '@foxui/visual';
14
15 interface PhotoItem {
16 uri: string;
17 value: {
18 photo: { $type: 'blob'; ref: { $link: string } };
19 aspectRatio: { width: number; height: number };
20 position?: number;
21 };
22 }
23
24 let { item }: { item: Item } = $props();
25
26 const data = getAdditionalUserData();
27 // svelte-ignore state_referenced_locally
28 let feed = $state(
29 (data[item.cardType] as Record<string, PhotoItem[]> | undefined)?.[item.cardData.galleryUri]
30 );
31
32 let did = getDidContext();
33 let handle = getHandleContext();
34
35 onMount(async () => {
36 if (!feed) {
37 feed = (
38 (await CardDefinitionsByType[item.cardType]?.loadData?.([item], {
39 did,
40 handle
41 })) as Record<string, PhotoItem[]> | undefined
42 )?.[item.cardData.galleryUri];
43
44 data[item.cardType] = feed;
45 }
46 });
47
48 let images = $derived(
49 (feed
50 ?.toSorted((a: PhotoItem, b: PhotoItem) => {
51 return (a.value.position ?? 0) - (b.value.position ?? 0);
52 })
53 .map((i: PhotoItem) => {
54 const item = parseUri(i.uri);
55 return {
56 src: getCDNImageBlobUrl({ did: item?.repo, blob: i.value.photo }),
57 name: '',
58 width: i.value.aspectRatio.width,
59 height: i.value.aspectRatio.height,
60 position: i.value.position ?? 0
61 };
62 })
63 .filter((i) => i.src !== undefined) || []) as {
64 src: string;
65 name: string;
66 width: number;
67 height: number;
68 position: number;
69 }[]
70 );
71
72 let isMobile = getIsMobile();
73</script>
74
75<div class="z-10 flex h-full w-full flex-col gap-4 overflow-y-scroll p-4">
76 <ImageMasonry
77 images={images ?? []}
78 showNames={false}
79 maxColumns={!isMobile() && item.w > 4 ? 3 : 2}
80 />
81</div>