···1<script lang="ts">
02 import type { ContentComponentProps } from '../../types';
3 import { onMount, onDestroy } from 'svelte';
4···196 }
197198 function handleKeyDown(e: KeyboardEvent) {
00199 if (e.code === 'Space' || e.code === 'ArrowUp' || e.code === 'KeyW') {
200 e.preventDefault();
201 jump();
···1<script lang="ts">
2+ import { isTyping } from '$lib/helper';
3 import type { ContentComponentProps } from '../../types';
4 import { onMount, onDestroy } from 'svelte';
5···197 }
198199 function handleKeyDown(e: KeyboardEvent) {
200+ if(isTyping()) return;
201+202 if (e.code === 'Space' || e.code === 'ArrowUp' || e.code === 'KeyW') {
203 e.preventDefault();
204 jump();
+1-1
src/lib/cards/GameCards/DinoGameCard/index.ts
···1-import type { CardDefinition } from '../types';
2import DinoGameCard from './DinoGameCard.svelte';
3import SidebarItemDinoGameCard from './SidebarItemDinoGameCard.svelte';
4
···1+import type { CardDefinition } from '$lib/cards/types';
2import DinoGameCard from './DinoGameCard.svelte';
3import SidebarItemDinoGameCard from './SidebarItemDinoGameCard.svelte';
4
+1-1
src/lib/cards/ImageCard/ImageCard.svelte
···1<script lang="ts">
2 import { getDidContext } from '$lib/website/context';
3- import { getImageBlobUrl } from '$lib/website/utils';
4 import type { ContentComponentProps } from '../types';
56 let { item = $bindable(), ...rest }: ContentComponentProps = $props();
···1<script lang="ts">
2 import { getDidContext } from '$lib/website/context';
3+ import { getImageBlobUrl } from '$lib/oauth/utils';
4 import type { ContentComponentProps } from '../types';
56 let { item = $bindable(), ...rest }: ContentComponentProps = $props();
+1-1
src/lib/cards/ImageCard/index.ts
···1-import { uploadBlob } from '$lib/website/utils';
2import type { CardDefinition } from '../types';
3import CreateImageCardModal from './CreateImageCardModal.svelte';
4import ImageCard from './ImageCard.svelte';
···1+import { uploadBlob } from '$lib/oauth/utils';
2import type { CardDefinition } from '../types';
3import CreateImageCardModal from './CreateImageCardModal.svelte';
4import ImageCard from './ImageCard.svelte';
+1-1
src/lib/cards/LinkCard/EditingLinkCard.svelte
···1<script lang="ts">
2 import { browser } from '$app/environment';
3- import { getIsMobile } from '$lib/helper';
4 import type { ContentComponentProps } from '../types';
5 import PlainTextEditor from '../utils/PlainTextEditor.svelte';
6
···1<script lang="ts">
2 import { browser } from '$app/environment';
3+ import { getIsMobile } from '$lib/website/context';
4 import type { ContentComponentProps } from '../types';
5 import PlainTextEditor from '../utils/PlainTextEditor.svelte';
6
+1-1
src/lib/cards/LinkCard/LinkCard.svelte
···1<script lang="ts">
2 import { browser } from '$app/environment';
3- import { getIsMobile } from '$lib/helper';
4 import type { ContentComponentProps } from '../types';
56 let { item }: ContentComponentProps = $props();
···1<script lang="ts">
2 import { browser } from '$app/environment';
3+ import { getIsMobile } from '$lib/website/context';
4 import type { ContentComponentProps } from '../types';
56 let { item }: ContentComponentProps = $props();
···1import { client } from '$lib/oauth';
2import { listRecords } from '$lib/oauth/atproto';
3-import { getImageBlobUrl } from '$lib/website/utils';
4import EmbedCard from '../EmbedCard/EmbedCard.svelte';
5import type { CardDefinition } from '../types';
6import LivestreamCard from './LivestreamCard.svelte';
···1import { client } from '$lib/oauth';
2import { listRecords } from '$lib/oauth/atproto';
3+import { getImageBlobUrl } from '$lib/oauth/utils';
4import EmbedCard from '../EmbedCard/EmbedCard.svelte';
5import type { CardDefinition } from '../types';
6import LivestreamCard from './LivestreamCard.svelte';
···1-export const image_collection = 'com.example.image' as const;
2-3-// collections and records we want to grab
4-export const data = {
5- 'app.bsky.actor.profile': ['self'],
6-7- 'app.blento.card': 'all',
8- 'app.blento.settings': ['self']
9-} as const;
···000000000
+106-113
src/lib/website/load.ts
···1-import {
2- type Collection,
3- type DownloadedData,
4- type IndividualCollections,
5- type ListCollections
6-} from './types';
7-import { getRecord, listRecords, resolveHandle } from '$lib/oauth/atproto';
8import type { Record as ListRecord } from '@atproto/api/dist/client/types/com/atproto/repo/listRecords';
9-import { data } from './data';
10import { CardDefinitionsByType } from '$lib/cards';
11-import type { Item } from '$lib/types';
12-import { compactItems, fixAllCollisions, fixCollisions } from '$lib/helper';
001314-type LoadedData = {
15- did: string;
16- data: DownloadedData;
17- additionalData: Record<string, unknown>;
18- updatedAt: number;
19-};
2021-export async function loadData(
22- handle: string,
23- platform?: App.Platform,
24- forceUpdate: boolean = false
25-): Promise<LoadedData> {
26- console.log(handle);
27- if (!forceUpdate) {
28- try {
29- const cachedResult = await platform?.env?.USER_DATA_CACHE?.get(handle);
3031- if (cachedResult) {
32- const result = JSON.parse(cachedResult);
33- const update = result.updatedAt;
34- const timePassed = (Date.now() - update) / 1000;
35- console.log(
36- 'using cached result for handle',
37- handle,
38- 'last update',
39- timePassed,
40- 'seconds ago'
41- );
42- return checkData(migrateData(JSON.parse(cachedResult)));
43- }
44- } catch (error) {
45- console.log('getting cached result failed', error);
46 }
000000000000047 }
04849- const did = await resolveHandle({ handle });
0000005051- const downloadedData = {} as DownloadedData;
05253- const promises: {
54- collection: string;
55- rkey?: string;
56- record: Promise<ListRecord> | Promise<Record<string, ListRecord>>;
57- }[] = [];
5859- for (const collection of Object.keys(data) as Collection[]) {
60- const cfg = data[collection];
6162- try {
63- if (Array.isArray(cfg)) {
64- for (const rkey of cfg) {
65- const record = getRecord({ did, collection, rkey }).catch((error) => {
66- console.error('error getting record', rkey, 'for collection', collection);
67- });
68- promises.push({
69- collection,
70- rkey,
71- record
72- });
73- }
74- } else if (cfg === 'all') {
75- const records = listRecords({ did, collection }).catch((error) => {
76- console.error('error getting records for collection', collection);
77- });
78- promises.push({ collection, record: records });
79- }
80- } catch (error) {
81- console.error('failed getting', collection, cfg, error);
82- }
83- }
8485- await Promise.all(promises.map((v) => v.record));
0008687- for (const promise of promises) {
88- if (promise.rkey) {
89- downloadedData[promise.collection as IndividualCollections] ??= {} as Record<
90- string,
91- ListRecord
92- >;
93- downloadedData[promise.collection as IndividualCollections][promise.rkey] =
94- (await promise.record) as ListRecord;
95- } else {
96- downloadedData[promise.collection as ListCollections] ??= (await promise.record) as Record<
97- string,
98- ListRecord
99- >;
100 }
101- }
102103- const cardTypes = new Set(
104- Object.values(downloadedData['app.blento.card']).map((v) => v.value.cardType) as string[]
105- );
1060107 const cardTypesArray = Array.from(cardTypes);
108109 const additionDataPromises: Record<string, Promise<unknown>> = {};
110111- const loadOptions = { did, handle, platform };
112113 for (const cardType of cardTypesArray) {
114 const cardDef = CardDefinitionsByType[cardType];
115116- if (cardDef.loadData) {
117- additionDataPromises[cardType] = cardDef
118- .loadData(
119- Object.values(downloadedData['app.blento.card'])
120- .filter((v) => cardType == v.value.cardType)
121- .map((v) => v.value) as Item[],
122- loadOptions
123- )
124- .catch((error) => {
125- console.error('error getting additional data for', cardType, error);
126- });
127- }
128 }
129130 await Promise.all(Object.values(additionDataPromises));
···139 }
140141 const result = {
00142 did,
143- data: JSON.parse(JSON.stringify(downloadedData)) as DownloadedData,
000144 additionalData,
145- updatedAt: Date.now()
00146 };
147148- await platform?.env?.USER_DATA_CACHE?.put(handle, JSON.stringify(result));
000000149150- return checkData(migrateData(result));
00151}
152153-function migrateFromV0ToV1(data: LoadedData): LoadedData {
154- for (const card of Object.values(data.data['app.blento.card']).map((i) => i.value) as Item[]) {
155 if (card.version) continue;
156 card.x *= 2;
157 card.y *= 2;
···167 return data;
168}
169170-function checkData(data: LoadedData): LoadedData {
171- const cards = Object.values(data.data['app.blento.card']).map((i) => i.value) as Item[];
000000000000172173- console.log(cards);
174 if (cards.length > 0) {
175 fixAllCollisions(cards);
176 fixAllCollisions(cards, true);
···179 compactItems(cards, true);
180 }
18100182 return data;
183}
184185-function migrateData(data: LoadedData): LoadedData {
186- return migrateFromV0ToV1(data);
187}
···1-import type { data } from './data';
2-import type { Record as ListRecord } from '@atproto/api/dist/client/types/com/atproto/repo/listRecords';
3-4-export type Collection = keyof typeof data;
5-6-export type IndividualCollections = {
7- [K in Collection]: (typeof data)[K] extends readonly unknown[] ? K : never;
8-}[Collection];
9-10-export type ListCollections = Exclude<Collection, IndividualCollections>;
11-12-export type ElementType<C extends Collection> = (typeof data)[C] extends readonly (infer U)[]
13- ? U
14- : unknown;
15-16-export type DownloadedData = { [C in Collection]: Record<string, ListRecord> };