diff --git a/hooks/use-auto-save.ts b/hooks/use-auto-save.ts new file mode 100644 index 0000000..af39eb4 --- /dev/null +++ b/hooks/use-auto-save.ts @@ -0,0 +1,188 @@ +import { useEffect, useRef } from 'react'; +import { useLayerStore } from '@/store'; +import { toast } from '@/lib/toast-utils'; + +const AUTO_SAVE_KEY = 'paint-ui-autosave'; +const AUTO_SAVE_INTERVAL = 30000; // 30 seconds + +interface AutoSaveData { + timestamp: number; + layers: any[]; +} + +/** + * Auto-save hook - saves project to localStorage periodically + */ +export function useAutoSave() { + const { layers } = useLayerStore(); + const lastSaveRef = useRef(0); + const saveTimeoutRef = useRef(null); + + // Save project to localStorage + const saveProject = () => { + try { + const saveData: AutoSaveData = { + timestamp: Date.now(), + layers: layers.map((layer) => ({ + ...layer, + canvas: layer.canvas ? layer.canvas.toDataURL() : null, + mask: layer.mask?.canvas ? { + ...layer.mask, + canvas: layer.mask.canvas.toDataURL(), + } : null, + })), + }; + + localStorage.setItem(AUTO_SAVE_KEY, JSON.stringify(saveData)); + lastSaveRef.current = Date.now(); + } catch (error) { + console.error('Auto-save failed:', error); + } + }; + + // Auto-save on interval + useEffect(() => { + if (layers.length === 0) return; + + // Clear existing timeout + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current); + } + + // Schedule next save + saveTimeoutRef.current = setTimeout(() => { + saveProject(); + }, AUTO_SAVE_INTERVAL); + + return () => { + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current); + } + }; + }, [layers]); + + return { + saveProject, + lastSave: lastSaveRef.current, + }; +} + +/** + * Check if auto-saved project exists + */ +export function hasAutoSave(): boolean { + if (typeof window === 'undefined') return false; + return localStorage.getItem(AUTO_SAVE_KEY) !== null; +} + +/** + * Load auto-saved project + */ +export async function loadAutoSave(): Promise { + try { + const saved = localStorage.getItem(AUTO_SAVE_KEY); + if (!saved) return false; + + const data: AutoSaveData = JSON.parse(saved); + const { clearLayers, createLayer } = useLayerStore.getState(); + + // Clear existing layers + clearLayers(); + + // Restore layers + for (const savedLayer of data.layers) { + const layer = createLayer({ + name: savedLayer.name, + width: savedLayer.width, + height: savedLayer.height, + x: savedLayer.x, + y: savedLayer.y, + opacity: savedLayer.opacity, + blendMode: savedLayer.blendMode, + }); + + // Restore canvas + if (savedLayer.canvas && layer.canvas) { + const img = new Image(); + await new Promise((resolve, reject) => { + img.onload = resolve; + img.onerror = reject; + img.src = savedLayer.canvas; + }); + + const ctx = layer.canvas.getContext('2d'); + if (ctx) { + ctx.drawImage(img, 0, 0); + } + } + + // Restore mask + if (savedLayer.mask?.canvas) { + const maskCanvas = document.createElement('canvas'); + maskCanvas.width = savedLayer.width; + maskCanvas.height = savedLayer.height; + + const maskImg = new Image(); + await new Promise((resolve, reject) => { + maskImg.onload = resolve; + maskImg.onerror = reject; + maskImg.src = savedLayer.mask.canvas; + }); + + const maskCtx = maskCanvas.getContext('2d'); + if (maskCtx) { + maskCtx.drawImage(maskImg, 0, 0); + } + + useLayerStore.getState().updateLayer(layer.id, { + mask: { + canvas: maskCanvas, + enabled: savedLayer.mask.enabled, + inverted: savedLayer.mask.inverted, + }, + }); + } + + // Restore other properties + useLayerStore.getState().updateLayer(layer.id, { + visible: savedLayer.visible, + locked: savedLayer.locked, + order: savedLayer.order, + }); + } + + const date = new Date(data.timestamp); + toast.success(`Auto-save restored from ${date.toLocaleTimeString()}`); + return true; + } catch (error) { + console.error('Failed to load auto-save:', error); + toast.error('Failed to restore auto-save'); + return false; + } +} + +/** + * Clear auto-save + */ +export function clearAutoSave(): void { + if (typeof window !== 'undefined') { + localStorage.removeItem(AUTO_SAVE_KEY); + } +} + +/** + * Get auto-save timestamp + */ +export function getAutoSaveTime(): Date | null { + if (typeof window === 'undefined') return null; + + const saved = localStorage.getItem(AUTO_SAVE_KEY); + if (!saved) return null; + + try { + const data: AutoSaveData = JSON.parse(saved); + return new Date(data.timestamp); + } catch { + return null; + } +}