@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
JavaScript
"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