Lock button
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import JSZip from 'jszip';
|
||||
import type { Manifest, AssetStore } from './types';
|
||||
import type { Manifest, AssetStore, Item } from './types';
|
||||
import { state } from './state.svelte';
|
||||
|
||||
export async function exportBoard(): Promise<{
|
||||
@@ -110,3 +110,78 @@ export async function importBoard(
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function mergeBoard(
|
||||
file: File,
|
||||
): Promise<{ success: boolean; error?: string; itemCount?: number }> {
|
||||
try {
|
||||
const zip = await JSZip.loadAsync(file);
|
||||
|
||||
const manifestFile = zip.file('manifest.json');
|
||||
if (!manifestFile)
|
||||
throw new Error('Invalid .bub file: missing manifest.json');
|
||||
|
||||
const manifestJson = await manifestFile.async('string');
|
||||
const raw = JSON.parse(manifestJson);
|
||||
|
||||
if (raw.version !== 1)
|
||||
throw new Error(`Unsupported manifest version: ${raw.version}`);
|
||||
|
||||
const incomingItems: Item[] = raw.items;
|
||||
if (incomingItems.length === 0) {
|
||||
return { success: true, itemCount: 0 };
|
||||
}
|
||||
|
||||
const assetIdMap = new Map<string, string>();
|
||||
const newAssets: AssetStore = {};
|
||||
|
||||
for (const item of incomingItems) {
|
||||
if (item.assetId && !assetIdMap.has(item.assetId)) {
|
||||
const newAssetId = crypto.randomUUID();
|
||||
assetIdMap.set(item.assetId, newAssetId);
|
||||
|
||||
const assetFiles = zip
|
||||
.folder('assets')
|
||||
?.file(new RegExp(`^${item.assetId}\\.`));
|
||||
if (assetFiles && assetFiles.length > 0) {
|
||||
const assetFile = assetFiles[0];
|
||||
const blob = await assetFile.async('blob');
|
||||
const url = URL.createObjectURL(blob);
|
||||
const filename = assetFile.name.split('/').pop() || 'asset';
|
||||
newAssets[newAssetId] = { blob, url, filename };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const minZIndex = Math.min(...incomingItems.map((i) => i.zIndex));
|
||||
const zIndexOffset = state.maxZIndex + 1 - minZIndex;
|
||||
|
||||
const newItems: Item[] = incomingItems.map((item) => {
|
||||
const newId = crypto.randomUUID();
|
||||
const newAssetId = item.assetId ? assetIdMap.get(item.assetId) : undefined;
|
||||
|
||||
let html = item.html;
|
||||
if (newAssetId && newAssets[newAssetId]) {
|
||||
html = html.replace(/src="[^"]*"/g, `src="${newAssets[newAssetId].url}"`);
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
id: newId,
|
||||
assetId: newAssetId,
|
||||
zIndex: item.zIndex + zIndexOffset,
|
||||
html,
|
||||
};
|
||||
});
|
||||
|
||||
state.addAssets(newAssets);
|
||||
state.addItems(newItems);
|
||||
|
||||
return { success: true, itemCount: newItems.length };
|
||||
} catch (e) {
|
||||
return {
|
||||
success: false,
|
||||
error: e instanceof Error ? e.message : 'Merge failed',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user