your personal website on atproto - mirror blento.app

add germ card

Florian 34efea62 dd0079fd

+121 -2
+3 -1
src/lib/cards/index.ts
··· 49 49 import { PlyrFMCardDefinition, PlyrFMCollectionCardDefinition } from './media/PlyrFMCard'; 50 50 import { MarginCardDefinition } from './social/MarginCard'; 51 51 import { SembleCollectionCardDefinition } from './social/SembleCollectionCard'; 52 + import { GermDMCardDefinition } from './social/GermDMCard'; 52 53 // import { Model3DCardDefinition } from './visual/Model3DCard'; 53 54 54 55 export const AllCardDefinitions = [ ··· 103 104 PlyrFMCardDefinition, 104 105 PlyrFMCollectionCardDefinition, 105 106 MarginCardDefinition, 106 - SembleCollectionCardDefinition 107 + SembleCollectionCardDefinition, 108 + GermDMCardDefinition 107 109 ] as const; 108 110 109 111 export const CardDefinitionsByType = AllCardDefinitions.reduce(
+73
src/lib/cards/social/GermDMCard/GermDMCard.svelte
··· 1 + <script lang="ts"> 2 + import { onMount } from 'svelte'; 3 + import { getAdditionalUserData, getDidContext, getHandleContext } from '$lib/website/context'; 4 + import type { ContentComponentProps } from '../../types'; 5 + import { CardDefinitionsByType } from '../..'; 6 + import { user } from '$lib/atproto/auth.svelte'; 7 + import { platformsData } from '../BigSocialCard'; 8 + 9 + let { item = $bindable(), isEditing }: ContentComponentProps = $props(); 10 + 11 + const data = getAdditionalUserData(); 12 + 13 + let germData = $state( 14 + data[item.cardType] as { messageMeUrl: string; showButtonTo: string } | null | undefined 15 + ); 16 + 17 + let did = getDidContext(); 18 + let handle = getHandleContext(); 19 + let isLoaded = $state(false); 20 + 21 + onMount(async () => { 22 + if (!germData) { 23 + germData = (await CardDefinitionsByType[item.cardType]?.loadData?.([], { 24 + did, 25 + handle 26 + })) as { messageMeUrl: string; showButtonTo: string } | null | undefined; 27 + 28 + data[item.cardType] = germData; 29 + isLoaded = true; 30 + } 31 + }); 32 + 33 + const brandColor = `#${platformsData.germ.hex}`; 34 + 35 + const dmUrl = $derived.by(() => { 36 + if (!germData?.messageMeUrl) return undefined; 37 + const viewerDid = user.did; 38 + const fragment = viewerDid ? `${did}+${viewerDid}` : `${did}`; 39 + return `${germData.messageMeUrl}/web#${fragment}`; 40 + }); 41 + </script> 42 + 43 + {#if germData && dmUrl} 44 + <div 45 + class="flex h-full w-full items-center justify-center p-10" 46 + style="background-color: {brandColor}" 47 + > 48 + <div 49 + class="flex aspect-square max-h-full max-w-full items-center justify-center [&_svg]:size-full [&_svg]:max-w-60 [&_svg]:fill-white" 50 + > 51 + {@html platformsData.germ.svg} 52 + </div> 53 + </div> 54 + 55 + {#if !isEditing} 56 + <a href={dmUrl} target="_blank" rel="noopener noreferrer"> 57 + <div class="absolute inset-0 z-50"></div> 58 + <span class="sr-only">Message me on Germ</span> 59 + </a> 60 + {/if} 61 + {:else if isLoaded} 62 + <div 63 + class="text-base-500 dark:text-base-400 accent:text-white/70 flex h-full w-full items-center justify-center p-4 text-center text-sm" 64 + > 65 + Germ DM not available 66 + </div> 67 + {:else} 68 + <div 69 + class="text-base-500 dark:text-base-400 accent:text-white/70 flex h-full w-full items-center justify-center p-4 text-center text-sm" 70 + > 71 + Loading... 72 + </div> 73 + {/if}
+42
src/lib/cards/social/GermDMCard/index.ts
··· 1 + import { getRecord } from '$lib/atproto'; 2 + import type { CardDefinition } from '../../types'; 3 + import { platformsData } from '../BigSocialCard'; 4 + import GermDMCard from './GermDMCard.svelte'; 5 + 6 + const germ = platformsData.germ; 7 + 8 + export const GermDMCardDefinition = { 9 + type: 'germDM', 10 + contentComponent: GermDMCard, 11 + createNew: (card) => { 12 + card.w = 2; 13 + card.h = 2; 14 + card.mobileW = 4; 15 + card.mobileH = 4; 16 + card.cardData.label = 'Message me'; 17 + }, 18 + loadData: async (_items, { did }) => { 19 + try { 20 + const record = await getRecord({ 21 + did, 22 + collection: 'com.germnetwork.declaration', 23 + rkey: 'self' 24 + }); 25 + const value = record?.value; 26 + if (!value?.messageMe) return null; 27 + return { 28 + messageMeUrl: value.messageMe.messageMeUrl, 29 + showButtonTo: value.messageMe.showButtonTo 30 + }; 31 + } catch { 32 + return null; 33 + } 34 + }, 35 + defaultColor: 'transparent', 36 + allowSetColor: false, 37 + canHaveLabel: true, 38 + name: 'DM on Germ', 39 + keywords: ['germ', 'dm', 'message', 'chat', 'encrypted'], 40 + groups: ['Social'], 41 + icon: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="size-4">${germ.svg.replace(/<svg[^>]*>/, '').replace(/<\/svg>/, '')}</svg>` 42 + } as CardDefinition & { type: 'germDM' };
+3 -1
src/lib/website/Context.svelte
··· 20 20 setAdditionalUserData(data.additionalData); 21 21 22 22 setCanEdit( 23 - () => (dev && isEditing === true) || (user.isLoggedIn && user.profile?.did === data.did && isEditing === true) 23 + () => 24 + (dev && isEditing === true) || 25 + (user.isLoggedIn && user.profile?.did === data.did && isEditing === true) 24 26 ); 25 27 26 28 // svelte-ignore state_referenced_locally