From 5624e3a8b7650ff0307ec3426568a6375baada19 Mon Sep 17 00:00:00 2001 From: DiTus Date: Fri, 20 Mar 2026 08:32:52 +0100 Subject: [PATCH] feat: implement persistence for settings and indicators --- js/ui/chart.js | 8 +++- js/ui/indicators-panel-new.js | 81 ++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/js/ui/chart.js b/js/ui/chart.js index caf3461..d8b6771 100644 --- a/js/ui/chart.js +++ b/js/ui/chart.js @@ -140,7 +140,10 @@ export class TradingDashboard { constructor() { this.chart = null; this.candleSeries = null; - this.currentInterval = '1d'; + // Load settings from local storage or defaults + this.symbol = localStorage.getItem('winterfail_symbol') || 'BTC'; + this.currentInterval = localStorage.getItem('winterfail_interval') || '1d'; + this.intervals = INTERVALS; this.allData = new Map(); this.isLoading = false; @@ -164,7 +167,7 @@ constructor() { let candles = this.allData.get(interval); if (!candles || candles.length < 125) { - const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=BTC&interval=${interval}&limit=1000`); + const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=${this.symbol}&interval=${interval}&limit=1000`); const data = await response.json(); if (data.candles && data.candles.length > 0) { candles = data.candles.reverse().map(c => ({ @@ -1044,6 +1047,7 @@ switchTimeframe(interval) { const oldInterval = this.currentInterval; this.currentInterval = interval; + localStorage.setItem('winterfail_interval', interval); // Save setting this.hasInitialLoad = false; document.querySelectorAll('.timeframe-btn').forEach(btn => { diff --git a/js/ui/indicators-panel-new.js b/js/ui/indicators-panel-new.js index 830b34f..dfb67cf 100644 --- a/js/ui/indicators-panel-new.js +++ b/js/ui/indicators-panel-new.js @@ -3,6 +3,72 @@ import { getAvailableIndicators, IndicatorRegistry as IR } from '../indicators/i // State management let activeIndicators = []; +// Persistence Logic +function saveActiveIndicators() { + try { + const toSave = activeIndicators.map(ind => ({ + id: ind.id, + type: ind.type, + name: ind.name, + params: ind.params, + visible: ind.visible, + paneHeight: ind.paneHeight + })); + console.log('[Persistence] Saving indicators:', toSave.length); + localStorage.setItem('winterfail_active_indicators', JSON.stringify(toSave)); + } catch (e) { + console.error('Failed to save active indicators:', e); + } +} + +function loadActiveIndicators() { + try { + const saved = localStorage.getItem('winterfail_active_indicators'); + console.log('[Persistence] Loading from storage:', saved ? 'data found' : 'empty'); + if (!saved) return; + + const parsed = JSON.parse(saved); + if (!Array.isArray(parsed)) return; + + const restored = []; + + parsed.forEach(savedInd => { + const IndicatorClass = IR?.[savedInd.type]; + if (!IndicatorClass) { + console.warn(`[Persistence] Unknown indicator type: ${savedInd.type}`); + return; + } + + const instance = new IndicatorClass({ type: savedInd.type, params: savedInd.params, name: savedInd.name }); + const metadata = instance.getMetadata(); + + restored.push({ + id: savedInd.id, + type: savedInd.type, + name: savedInd.name || metadata.name, + params: savedInd.params, + plots: metadata.plots, + series: [], + visible: savedInd.visible !== undefined ? savedInd.visible : true, + paneHeight: savedInd.paneHeight || 120, + cachedResults: null, + cachedMeta: null + }); + + const parts = savedInd.id.split('_'); + const idNum = parseInt(parts[parts.length - 1]); + if (!isNaN(idNum) && idNum >= nextInstanceId) { + nextInstanceId = idNum + 1; + } + }); + + activeIndicators = restored; + console.log(`[Persistence] Successfully restored ${activeIndicators.length} indicators`); + } catch (e) { + console.error('Failed to load active indicators:', e); + } +} + console.log('[Module] indicators-panel-new.js loaded - activeIndicators count:', activeIndicators?.length || 0); let configuringId = null; let searchQuery = ''; @@ -96,7 +162,12 @@ function groupPlotsByColor(plots) { } export function initIndicatorPanel() { + loadActiveIndicators(); // Load persisted indicators renderIndicatorPanel(); + // Also trigger initial draw if dashboard exists (it might be too early, but safe to try) + if (window.dashboard && window.dashboard.hasInitialLoad) { + drawIndicatorsOnChart(); + } } export function getActiveIndicators() { @@ -107,6 +178,7 @@ export function setActiveIndicators(indicators) { console.warn('setActiveIndicators() called with', indicators.length, 'indicators - this will replace activeIndicators array!'); console.trace('Call stack:'); activeIndicators = indicators; + saveActiveIndicators(); renderIndicatorPanel(); } @@ -557,6 +629,7 @@ window.updateIndicatorColor = function(id, index, color) { if (!indicator) return; indicator.params[`_color_${index}`] = color; + saveActiveIndicators(); drawIndicatorsOnChart(); }; @@ -568,6 +641,7 @@ window.updateIndicatorSetting = function(id, key, value) { indicator.lastSignalTimestamp = null; indicator.lastSignalType = null; indicator.cachedResults = null; // Clear cache when params change + saveActiveIndicators(); drawIndicatorsOnChart(); }; @@ -579,6 +653,7 @@ window.clearAllIndicators = function() { }); activeIndicators = []; configuringId = null; + saveActiveIndicators(); renderIndicatorPanel(); drawIndicatorsOnChart(); } @@ -590,6 +665,7 @@ window.toggleAllIndicatorsVisibility = function() { ind.visible = !allVisible; }); + saveActiveIndicators(); drawIndicatorsOnChart(); renderIndicatorPanel(); } @@ -608,6 +684,7 @@ function removeIndicatorById(id) { configuringId = null; } + saveActiveIndicators(); renderIndicatorPanel(); drawIndicatorsOnChart(); } @@ -808,7 +885,7 @@ function addIndicator(type) { paneHeight: 120 // default 120px }); - // Don't set configuringId so indicators are NOT expanded by default + saveActiveIndicators(); renderIndicatorPanel(); drawIndicatorsOnChart(); }; @@ -1286,6 +1363,7 @@ function resetIndicator(id) { indicator.params[input.name] = input.default; }); + saveActiveIndicators(); renderIndicatorPanel(); drawIndicatorsOnChart(); } @@ -1302,6 +1380,7 @@ function toggleIndicatorVisibility(id) { indicator.visible = indicator.visible === false; + saveActiveIndicators(); // Full redraw to ensure all indicators render correctly if (typeof drawIndicatorsOnChart === 'function') { drawIndicatorsOnChart();