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