Initial commit

This commit is contained in:
Robert Nasarek 2026-06-25 09:11:23 +02:00
commit 05c65aad4d
155 changed files with 93617 additions and 0 deletions

117
viewer/extract-helper.js Normal file
View file

@ -0,0 +1,117 @@
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;
};