/** * Adaptive Tactics - Persistence Layer * Handles localStorage with graceful fallback to in-memory storage */ // In-memory fallback storage const memoryStorage = new Map(); // Check if localStorage is available let storageAvailable = false; try { const testKey = '__at_test__'; localStorage.setItem(testKey, testKey); localStorage.removeItem(testKey); storageAvailable = true; } catch (e) { console.warn('localStorage not available, using in-memory storage'); storageAvailable = false; } /** * Save data to storage * @param {string} key - Storage key * @param {any} data - Data to store (will be JSON serialized) * @returns {boolean} Success status */ export function save(key, data) { try { const serialized = JSON.stringify(data); if (storageAvailable) { localStorage.setItem(key, serialized); } else { memoryStorage.set(key, serialized); } return true; } catch (e) { console.error(`Failed to save data for key "${key}":`, e); return false; } } /** * Load data from storage * @param {string} key - Storage key * @returns {any|null} Parsed data or null if not found */ export function load(key) { try { let serialized; if (storageAvailable) { serialized = localStorage.getItem(key); } else { serialized = memoryStorage.get(key); } if (serialized === null || serialized === undefined) { return null; } return JSON.parse(serialized); } catch (e) { console.error(`Failed to load data for key "${key}":`, e); return null; } } /** * Remove data from storage * @param {string} key - Storage key * @returns {boolean} Success status */ export function remove(key) { try { if (storageAvailable) { localStorage.removeItem(key); } else { memoryStorage.delete(key); } return true; } catch (e) { console.error(`Failed to remove data for key "${key}":`, e); return false; } } /** * Clear all game-related storage * @returns {boolean} Success status */ export function clearAll() { try { if (storageAvailable) { // Only clear our keys, not all localStorage const keysToRemove = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith('at_')) { keysToRemove.push(key); } } keysToRemove.forEach(key => localStorage.removeItem(key)); } else { memoryStorage.clear(); } return true; } catch (e) { console.error('Failed to clear storage:', e); return false; } } /** * Check if storage is persistent (localStorage) or temporary (memory) * @returns {boolean} True if using localStorage */ export function isPersistent() { return storageAvailable; }