117 lines
No EOL
2.3 KiB
JavaScript
117 lines
No EOL
2.3 KiB
JavaScript
import { unzipSync } from 'fflate';
|
|
import { loadDroppedModel } from "./sandbox.js";
|
|
import { core } from "./core.js";
|
|
import { toastHelper } from './viewer-utils.js';
|
|
|
|
let archiveFileMap = {};
|
|
|
|
async function extractZip (archiveFile) {
|
|
const buffer = await archiveFile.arrayBuffer();
|
|
|
|
const unzipped = unzipSync(new Uint8Array(buffer));
|
|
|
|
const files = [];
|
|
|
|
Object.entries(unzipped).forEach(([path, data]) => {
|
|
// Skip folders
|
|
if (path.endsWith('/')) {
|
|
return;
|
|
}
|
|
|
|
files.push(
|
|
new File(
|
|
[data],
|
|
path,
|
|
{
|
|
type: 'application/octet-stream'
|
|
}
|
|
)
|
|
);
|
|
});
|
|
|
|
return files;
|
|
};
|
|
|
|
function cleanupArchiveUrls() {
|
|
Object.values(archiveFileMap).forEach(url => {
|
|
try {
|
|
URL.revokeObjectURL(url);
|
|
} catch (e) {}
|
|
});
|
|
|
|
archiveFileMap = {};
|
|
};
|
|
|
|
function buildArchiveFileMap (files) {
|
|
cleanupArchiveUrls();
|
|
|
|
files.forEach(file => {
|
|
const normalized = file.name.replace(/^\/+/, '');
|
|
archiveFileMap[normalized] = URL.createObjectURL(file);
|
|
});
|
|
};
|
|
|
|
export async function loadDroppedArchive (archiveFile) {
|
|
try {
|
|
const extension = archiveFile.name.split('.').pop().toLowerCase();
|
|
|
|
let extractedFiles = [];
|
|
|
|
switch (extension) {
|
|
case 'zip':
|
|
extractedFiles = await extractZip(archiveFile);
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unsupported archive type: ${extension}`);
|
|
}
|
|
|
|
if (!extractedFiles.length) {
|
|
throw new Error('Archive is empty');
|
|
}
|
|
|
|
const modelFile = findMainModelFile(extractedFiles);
|
|
|
|
if (!modelFile) {
|
|
throw new Error('No supported model file found in archive');
|
|
}
|
|
|
|
buildArchiveFileMap(extractedFiles);
|
|
|
|
await loadDroppedModel(modelFile);
|
|
|
|
} catch (err) {
|
|
console.error(err);
|
|
|
|
toastHelper("unsupportedFormat", "error");
|
|
}
|
|
};
|
|
|
|
function findMainModelFile (files) {
|
|
const priority = core.SUPPORTED_EXTENSIONS;
|
|
|
|
for (const ext of priority) {
|
|
const found = files.find(file => {
|
|
const fileExt = file.name.split('.').pop().toLowerCase();
|
|
return fileExt === ext;
|
|
});
|
|
|
|
if (found) {
|
|
return found;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
function resolveArchiveUrl (url) {
|
|
if (!url) {
|
|
return url;
|
|
}
|
|
|
|
const clean = url
|
|
.replace(/^(\.\/)+/, '')
|
|
.replace(/^\/+/, '');
|
|
|
|
return archiveFileMap[clean] || url;
|
|
}; |