feat: implement pwa, add dockerfiles for web and cli, and introduce folder selection with wasm error handling.
This commit is contained in:
@@ -59,6 +59,33 @@ header h1 {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
/* For folder button positioning */
|
||||
}
|
||||
|
||||
.folder-select-btn {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
/* Slight visibility */
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 0.5rem;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.folder-select-btn:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.dropzone:hover,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useDropzone } from 'react-dropzone'
|
||||
import { saveAs } from 'file-saver'
|
||||
import JSZip from 'jszip'
|
||||
import { FaCloudUploadAlt, FaFileExport, FaCheckCircle, FaSpinner, FaTrash } from 'react-icons/fa'
|
||||
import { MdError, Md3dRotation } from 'react-icons/md'
|
||||
import { MdError, Md3dRotation, MdFolderOpen } from 'react-icons/md'
|
||||
import './App.css'
|
||||
import { useManifold, convertFile } from './logic/useNametagConverter'
|
||||
|
||||
@@ -24,6 +24,21 @@ function App() {
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })
|
||||
|
||||
const onFolderSelect = (e) => {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
const selectedFiles = Array.from(e.target.files);
|
||||
const svgs = selectedFiles.filter(f => f.name.toLowerCase().endsWith('.svg') && !f.name.startsWith('._') && !f.name.startsWith('.'));
|
||||
if (svgs.length > 0) {
|
||||
setFiles(prev => [...prev, ...svgs]);
|
||||
addLog(`Added ${svgs.length} SVG files from folder.`);
|
||||
} else {
|
||||
addLog(`No SVG files found in selected folder.`);
|
||||
}
|
||||
}
|
||||
// Reset
|
||||
e.target.value = null;
|
||||
}
|
||||
|
||||
const processQueue = async () => {
|
||||
if (!manifold) {
|
||||
alert("WASM Engine still loading... please wait a moment.")
|
||||
@@ -83,6 +98,27 @@ function App() {
|
||||
<main>
|
||||
<div {...getRootProps()} className={`dropzone ${isDragActive ? 'active' : ''}`}>
|
||||
<input {...getInputProps()} />
|
||||
|
||||
{/* Folder Selection Button */}
|
||||
<div
|
||||
className="folder-select-btn"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
title="Select Folder to Batch Process"
|
||||
>
|
||||
<label htmlFor="folder-input" style={{ cursor: 'pointer', display: 'flex' }}>
|
||||
<MdFolderOpen size={28} />
|
||||
</label>
|
||||
<input
|
||||
id="folder-input"
|
||||
type="file"
|
||||
webkitdirectory=""
|
||||
directory=""
|
||||
multiple
|
||||
style={{ display: 'none' }}
|
||||
onChange={onFolderSelect}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="dropzone-content">
|
||||
<FaCloudUploadAlt size={64} color={isDragActive ? "#00aeef" : "#666"} />
|
||||
{isDragActive ?
|
||||
|
||||
@@ -12,20 +12,25 @@ export const useManifold = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
if (!wasmModule) {
|
||||
// Fix: Explicitly tell Manifold where to find the WASM file
|
||||
// distinct from the bundle path
|
||||
wasmModule = await Module({
|
||||
locateFile: (path) => {
|
||||
if (path.endsWith('.wasm')) {
|
||||
return '/manifold.wasm';
|
||||
try {
|
||||
if (!wasmModule) {
|
||||
// Fix: Explicitly tell Manifold where to find the WASM file
|
||||
// distinct from the bundle path
|
||||
wasmModule = await Module({
|
||||
locateFile: (path) => {
|
||||
if (path.endsWith('.wasm')) {
|
||||
return '/manifold.wasm';
|
||||
}
|
||||
return path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
});
|
||||
wasmModule.setup();
|
||||
});
|
||||
wasmModule.setup();
|
||||
}
|
||||
setManifold(wasmModule);
|
||||
} catch (e) {
|
||||
console.error("WASM Init Failed:", e);
|
||||
// We could set an error state here, but for now logging prevents crash
|
||||
}
|
||||
setManifold(wasmModule);
|
||||
};
|
||||
init();
|
||||
}, []);
|
||||
@@ -158,7 +163,7 @@ export const convertFile = async (file, manifold, addLog) => {
|
||||
// Constants
|
||||
const BG_THICK = 3.0;
|
||||
const TXT_THICK = 2.0;
|
||||
const TXT_Z = 4.0; // Raised by 4mm
|
||||
const TXT_Z = 3.0; // Starts at 3mm, Center at 4mm
|
||||
|
||||
return {
|
||||
black: createMeshBlob(paths.black, BG_THICK, 0),
|
||||
|
||||
Reference in New Issue
Block a user