import { useState, useEffect, useCallback } from 'react'; import { useBrotherMachine } from './hooks/useBrotherMachine'; import { MachineConnection } from './components/MachineConnection'; import { FileUpload } from './components/FileUpload'; import { PatternCanvas } from './components/PatternCanvas'; import { ProgressMonitor } from './components/ProgressMonitor'; import { WorkflowStepper } from './components/WorkflowStepper'; import { NextStepGuide } from './components/NextStepGuide'; import type { PesPatternData } from './utils/pystitchConverter'; import { pyodideLoader } from './utils/pyodideLoader'; import { MachineStatus } from './types/machine'; import { hasError } from './utils/errorCodeHelpers'; import './App.css'; function App() { const machine = useBrotherMachine(); const [pesData, setPesData] = useState(null); const [pyodideReady, setPyodideReady] = useState(false); const [pyodideError, setPyodideError] = useState(null); const [patternOffset, setPatternOffset] = useState<{ x: number; y: number }>({ x: 0, y: 0 }); const [patternUploaded, setPatternUploaded] = useState(false); // Initialize Pyodide on mount useEffect(() => { pyodideLoader .initialize() .then(() => { setPyodideReady(true); console.log('[App] Pyodide initialized successfully'); }) .catch((err) => { setPyodideError(err instanceof Error ? err.message : 'Failed to initialize Python environment'); console.error('[App] Failed to initialize Pyodide:', err); }); }, []); // Auto-load cached pattern when available useEffect(() => { if (machine.resumedPattern && !pesData) { console.log('[App] Loading resumed pattern:', machine.resumeFileName, 'Offset:', machine.resumedPattern.patternOffset); setPesData(machine.resumedPattern.pesData); // Restore the cached pattern offset if (machine.resumedPattern.patternOffset) { setPatternOffset(machine.resumedPattern.patternOffset); } } }, [machine.resumedPattern, pesData, machine.resumeFileName]); const handlePatternLoaded = useCallback((data: PesPatternData) => { setPesData(data); // Reset pattern offset when new pattern is loaded setPatternOffset({ x: 0, y: 0 }); setPatternUploaded(false); }, []); const handlePatternOffsetChange = useCallback((offsetX: number, offsetY: number) => { setPatternOffset({ x: offsetX, y: offsetY }); console.log('[App] Pattern offset changed:', { x: offsetX, y: offsetY }); }, []); const handleUpload = useCallback(async (penData: Uint8Array, pesData: PesPatternData, fileName: string, patternOffset?: { x: number; y: number }) => { await machine.uploadPattern(penData, pesData, fileName, patternOffset); setPatternUploaded(true); }, [machine]); const handleDeletePattern = useCallback(async () => { await machine.deletePattern(); setPatternUploaded(false); // NOTE: We intentionally DON'T clear setPesData(null) here // so the pattern remains visible in the canvas for re-editing and re-uploading }, [machine]); // Track pattern uploaded state based on machine status useEffect(() => { if (!machine.isConnected) { setPatternUploaded(false); return; } // Pattern is uploaded if machine has pattern info if (machine.patternInfo !== null) { setPatternUploaded(true); } else { // No pattern info means no pattern on machine setPatternUploaded(false); } }, [machine.machineStatus, machine.patternInfo, machine.isConnected]); return (

SKiTCH Controller

{/* Workflow Stepper - Integrated in header when connected */} {machine.isConnected && (
)}
{/* Global errors */} {machine.error && (
Error: {machine.error}
)} {pyodideError && (
Python Error: {pyodideError}
)} {!pyodideReady && !pyodideError && (
Initializing Python environment...
)}
{/* Left Column - Controls */}
{/* Next Step Guide - Always visible */} {/* Machine Connection - Always visible */} {/* Pattern File - Only show when connected */} {machine.isConnected && ( )}
{/* Right Column - Pattern Preview */}
{pesData ? ( ) : (

Pattern Preview

{/* Decorative background pattern */}

No Pattern Loaded

Connect to your machine and choose a PES embroidery file to see your design preview

Drag to Position
Zoom & Pan
Real-time Preview
)} {/* Progress Monitor - Wide section below pattern preview */} {machine.isConnected && patternUploaded && ( )}
); } export default App;