respira/src/utils/pystitchConverter.ts
Jan-Henrik Bruhn 0dfc8b731b feature: Implement Web Worker-based pattern conversion with progress tracking
Move Pyodide/PyStitch pattern conversion to a dedicated Web Worker for
non-blocking UI performance. Pyodide now loads in the background on app
startup with real-time progress indicator showing download and initialization
status.

Key changes:
- Create patternConverter.worker.ts with full PES to PEN conversion logic
- Add patternConverterClient.ts singleton for worker management
- Implement progress tracking (0-100%) with step descriptions
- Add inline progress bar in FileUpload component with contextual messaging
- Configure COEP headers for Electron to support Web Workers
- Pass dynamic asset URLs to worker for file:// protocol support
- Update UIStore with progress state management
- Simplify pystitchConverter.ts to delegate to worker client

Benefits:
- Truly non-blocking UI (heavy Python/WASM runs off main thread)
- Real progress feedback during 15MB Pyodide download
- Works in both browser and Electron (dev and production)
- Faster app startup perception with background loading
- Better UX with "waiting" state if user clicks before ready

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-13 13:34:13 +01:00

39 lines
1 KiB
TypeScript

import { patternConverterClient, type PesPatternData } from "./patternConverterClient";
// Re-export the type for backwards compatibility
export type { PesPatternData };
/**
* Reads a PES file using PyStitch (via Web Worker) and converts it to PEN format
*/
export async function convertPesToPen(file: File): Promise<PesPatternData> {
// Delegate to the worker client
return await patternConverterClient.convertPesToPen(file);
}
/**
* Get thread color from pattern data
*/
export function getThreadColor(
data: PesPatternData,
colorIndex: number,
): string {
if (!data.threads || colorIndex < 0 || colorIndex >= data.threads.length) {
// Default colors if not specified or index out of bounds
const defaultColors = [
"#FF0000",
"#00FF00",
"#0000FF",
"#FFFF00",
"#FF00FF",
"#00FFFF",
"#FFA500",
"#800080",
];
const safeIndex = Math.max(0, colorIndex) % defaultColors.length;
return defaultColors[safeIndex];
}
return data.threads[colorIndex]?.hex || "#000000";
}