UNPKG

@jager-ai/holy-editor

Version:

Rich text editor with Bible verse slash commands and PWA keyboard tracking, extracted from Holy Habit project

282 lines â€ĸ 8.71 kB
"use strict"; /** * Auto Save Manager * * Manages automatic saving of editor content to localStorage * Extracted from Holy Habit auto-save functionality */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoSaveManager = void 0; class AutoSaveManager { constructor(editorId, options) { this.intervalId = null; this.lastSaveTime = 0; this.version = '1.0.0'; // Storage availability flag this.storageAvailable = false; this.editorId = editorId; this.storageKey = options?.key || `holy-editor-autosave-${editorId}`; this.saveInterval = options?.interval || 30000; // 30 seconds default this.maxSize = options?.maxSize || 1048576; // 1MB default // Set callbacks this.onSave = options?.onSave; this.onRestore = options?.onRestore; this.onError = options?.onError; // Check localStorage availability this.checkStorageAvailability(); console.log('💾 AutoSaveManager initialized for editor:', editorId); } /** * Check if localStorage is available */ checkStorageAvailability() { try { const testKey = '__holy_editor_test__'; localStorage.setItem(testKey, 'test'); localStorage.removeItem(testKey); this.storageAvailable = true; return true; } catch (error) { console.warn('âš ī¸ localStorage not available:', error); this.storageAvailable = false; this.handleError(new Error('localStorage not available')); return false; } } /** * Start auto-saving */ start(getContent) { if (!this.storageAvailable) { console.warn('âš ī¸ Cannot start auto-save: localStorage not available'); return; } // Clear any existing interval this.stop(); // Save immediately this.save(getContent()); // Set up interval this.intervalId = setInterval(() => { this.save(getContent()); }, this.saveInterval); console.log('â–ļī¸ Auto-save started with interval:', this.saveInterval); } /** * Stop auto-saving */ stop() { if (this.intervalId) { clearInterval(this.intervalId); this.intervalId = null; console.log('âšī¸ Auto-save stopped'); } } /** * Save content to localStorage */ save(content) { if (!this.storageAvailable) return false; try { // Check content size const contentSize = new Blob([content]).size; if (contentSize > this.maxSize) { throw new Error(`Content size (${contentSize} bytes) exceeds maximum (${this.maxSize} bytes)`); } // Create save data const saveData = { content, timestamp: Date.now(), version: this.version, editorId: this.editorId }; // Save to localStorage localStorage.setItem(this.storageKey, JSON.stringify(saveData)); this.lastSaveTime = saveData.timestamp; // Call onSave callback if (this.onSave) { this.onSave(saveData); } console.log('💾 Content auto-saved:', { size: contentSize, timestamp: new Date(saveData.timestamp).toISOString() }); return true; } catch (error) { console.error('❌ Auto-save failed:', error); this.handleError(error); return false; } } /** * Restore content from localStorage */ restore() { if (!this.storageAvailable) return null; try { const savedData = localStorage.getItem(this.storageKey); if (!savedData) { console.log('💾 No saved content found'); return null; } const data = JSON.parse(savedData); // Validate data structure if (!data.content || !data.timestamp || !data.version) { throw new Error('Invalid save data structure'); } // Check if saved data is from same editor if (data.editorId !== this.editorId) { console.warn('âš ī¸ Saved data is from different editor:', data.editorId); } // Call onRestore callback if (this.onRestore) { this.onRestore(data); } const age = Date.now() - data.timestamp; const ageMinutes = Math.floor(age / 60000); console.log('✅ Content restored:', { age: `${ageMinutes} minutes`, timestamp: new Date(data.timestamp).toISOString(), size: new Blob([data.content]).size }); return data.content; } catch (error) { console.error('❌ Failed to restore content:', error); this.handleError(error); return null; } } /** * Clear saved content */ clear() { if (!this.storageAvailable) return false; try { localStorage.removeItem(this.storageKey); console.log('đŸ—‘ī¸ Auto-saved content cleared'); return true; } catch (error) { console.error('❌ Failed to clear saved content:', error); this.handleError(error); return false; } } /** * Get save info without restoring content */ getSaveInfo() { if (!this.storageAvailable) return null; try { const savedData = localStorage.getItem(this.storageKey); if (!savedData) return null; const data = JSON.parse(savedData); const size = new Blob([data.content]).size; return { timestamp: data.timestamp, size }; } catch (error) { console.error('❌ Failed to get save info:', error); return null; } } /** * Check if there's saved content */ hasSavedContent() { return this.getSaveInfo() !== null; } /** * Get time since last save */ getTimeSinceLastSave() { if (this.lastSaveTime === 0) return -1; return Date.now() - this.lastSaveTime; } /** * Update save interval */ updateInterval(newInterval, getContent) { this.saveInterval = newInterval; // Restart if currently running if (this.intervalId && getContent) { this.start(getContent); } } /** * Handle errors */ handleError(error) { if (this.onError) { this.onError(error); } } /** * Get storage key */ getStorageKey() { return this.storageKey; } /** * Check if auto-save is running */ isRunning() { return this.intervalId !== null; } /** * Get all saved editor keys */ static getAllSavedEditors() { const keys = []; const prefix = 'holy-editor-autosave-'; try { for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith(prefix)) { keys.push(key.substring(prefix.length)); } } } catch (error) { console.error('❌ Failed to get saved editors:', error); } return keys; } /** * Clear all saved content for all editors */ static clearAll() { let cleared = 0; const prefix = 'holy-editor-autosave-'; try { const keysToRemove = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith(prefix)) { keysToRemove.push(key); } } keysToRemove.forEach(key => { localStorage.removeItem(key); cleared++; }); console.log(`đŸ—‘ī¸ Cleared ${cleared} auto-saved editors`); } catch (error) { console.error('❌ Failed to clear all saved content:', error); } return cleared; } } exports.AutoSaveManager = AutoSaveManager; //# sourceMappingURL=AutoSaveManager.js.map