your personal website on atproto - mirror blento.app

add /all route

Florian ea7b0b02 2fa92843

+102 -1
+20
src/lib/cards/BlueskyProfileCard/BlueskyProfileCard.svelte
··· 1 + <script lang="ts"> 2 + import type { Item } from '$lib/types'; 3 + 4 + let { item }: { item: Item } = $props(); 5 + </script> 6 + 7 + <a 8 + target="_blank" 9 + href="/{item.cardData.handle}" 10 + class="flex h-full w-full flex-col items-center justify-center gap-2 rounded-xl p-2 transition-colors duration-150" 11 + > 12 + <img 13 + src={item.cardData.avatar} 14 + class="aspect-square size-24 rounded-full transition-all duration-100 group-hover:scale-105" 15 + alt="" 16 + /> 17 + <div class="text-md line-clamp-1 text-center font-bold"> 18 + {item.cardData.displayName || item.cardData.handle} 19 + </div> 20 + </a>
+13
src/lib/cards/BlueskyProfileCard/index.ts
··· 1 + import type { CardDefinition } from '../types'; 2 + import BlueskyProfileCard from './BlueskyProfileCard.svelte'; 3 + 4 + export const BlueskyProfileCardDefinition = { 5 + type: 'blueskyProfile', 6 + contentComponent: BlueskyProfileCard, 7 + createNew: (card) => { 8 + // card.w = 4; 9 + // card.mobileW = 8; 10 + // card.h = 4; 11 + // card.mobileH = 8; 12 + } 13 + } as CardDefinition & { type: 'blueskyProfile' };
+3 -1
src/lib/cards/index.ts
··· 14 14 import { TextCardDefinition } from './TextCard'; 15 15 import type { CardDefinition } from './types'; 16 16 import { YoutubeCardDefinition } from './YoutubeVideo'; 17 + import { BlueskyProfileCardDefinition } from './BlueskyProfileCard'; 17 18 18 19 export const AllCardDefinitions = [ 19 20 ImageCardDefinition, ··· 30 31 ATProtoCollectionsCardDefinition, 31 32 SectionCardDefinition, 32 33 BlueskyMediaCardDefinition, 33 - DinoGameCardDefinition 34 + DinoGameCardDefinition, 35 + BlueskyProfileCardDefinition 34 36 ] as const; 35 37 36 38 export const CardDefinitionsByType = AllCardDefinitions.reduce(
+34
src/routes/all/+page.server.ts
··· 1 + import { env } from '$env/dynamic/public'; 2 + import type { UserCache, WebsiteData } from '$lib/types.js'; 3 + import { loadData } from '$lib/website/load'; 4 + import type { ProfileViewDetailed } from '@atproto/api/dist/client/types/app/bsky/actor/defs.js'; 5 + 6 + export async function load({ platform }) { 7 + const cache = platform?.env?.USER_DATA_CACHE; 8 + 9 + const list = await cache?.list(); 10 + 11 + const profiles: ProfileViewDetailed[] = []; 12 + for (const value of list?.keys ?? []) { 13 + // check if at least one card 14 + const result = await cache?.get(value.name); 15 + if (!result) continue; 16 + const parsed = JSON.parse(result) as WebsiteData; 17 + 18 + if (parsed.version !== 1 || !parsed.cards?.length) continue; 19 + 20 + profiles.push(parsed.profile); 21 + } 22 + 23 + profiles.sort((a, b) => a.handle.localeCompare(b.handle)); 24 + 25 + const handle = env.PUBLIC_HANDLE; 26 + 27 + const data = await loadData(handle, cache as unknown as UserCache); 28 + 29 + data.publication ??= {}; 30 + data.publication.preferences ??= {}; 31 + data.publication.preferences.hideProfile = true; 32 + 33 + return { ...data, profiles }; 34 + }
+32
src/routes/all/+page.svelte
··· 1 + <script lang="ts"> 2 + import { createEmptyCard, refreshData } from '$lib/helper.js'; 3 + import Website from '$lib/website/Website.svelte'; 4 + import { onMount } from 'svelte'; 5 + 6 + let { data } = $props(); 7 + 8 + $inspect(data.profiles); 9 + </script> 10 + 11 + <Website 12 + data={{ 13 + ...data, 14 + cards: data.profiles.map((v, i) => { 15 + const card = createEmptyCard(''); 16 + card.cardType = 'blueskyProfile'; 17 + card.cardData = { 18 + avatar: v.avatar, 19 + handle: v.handle, 20 + displayName: v.displayName 21 + }; 22 + 23 + card.x = (i % 4) * 2; 24 + card.y = Math.floor(i / 4) * 2; 25 + 26 + card.mobileX = (i % 2) * 4; 27 + card.mobileY = Math.floor(i / 2) * 4; 28 + 29 + return card; 30 + }) 31 + }} 32 + />