your personal website on atproto - mirror
blento.app
1import { uploadBlob } from '$lib/atproto';
2import type { CardDefinition } from '../types';
3import CreateModel3DCardModal from './CreateModel3DCardModal.svelte';
4import Model3DCard from './Model3DCard.svelte';
5
6export const Model3DCardDefinition = {
7 type: 'model3d',
8 contentComponent: Model3DCard,
9 creationModalComponent: CreateModel3DCardModal,
10 createNew: (card) => {
11 card.w = 4;
12 card.h = 4;
13 card.mobileW = 4;
14 card.mobileH = 4;
15 card.cardData = {
16 modelType: 'gltf' // 'gltf' | 'stl'
17 };
18 },
19
20 upload: async (item) => {
21 // Handle file upload
22 if (item.cardData.modelFile?.blob) {
23 let blob: Blob = item.cardData.modelFile.blob;
24 const modelType = item.cardData.modelFile.type || 'glb';
25
26 // Ensure blob has a MIME type (STL/FBX files often have empty type)
27 if (!blob.type) {
28 const mimeTypes: Record<string, string> = {
29 stl: 'model/stl',
30 glb: 'model/gltf-binary',
31 gltf: 'model/gltf+json',
32 fbx: 'application/octet-stream'
33 };
34 const mimeType = mimeTypes[modelType] || 'application/octet-stream';
35 blob = new Blob([blob], { type: mimeType });
36 }
37
38 // Upload the blob to the PDS
39 const uploadedBlob = await uploadBlob({ blob });
40
41 if (uploadedBlob) {
42 item.cardData.modelBlob = uploadedBlob;
43 item.cardData.modelType = modelType;
44 }
45
46 // Clean up the temporary file data
47 if (item.cardData.modelFile.objectUrl) {
48 URL.revokeObjectURL(item.cardData.modelFile.objectUrl);
49 }
50 delete item.cardData.modelFile;
51 }
52
53 return item;
54 },
55
56 minW: 2,
57 minH: 2,
58
59 name: '3D Model Card'
60} as CardDefinition & { type: 'model3d' };