fix(graph): T1 hardening — localStorage try/catch + rAF throttle on redraw

После T1 code-quality review: 2 Important issues из spec §9 mitigation list. (1) try/catch обернул read/write localStorage — в Edge InPrivate / quota-exceeded не падает, fallback на default 300. (2) network.redraw() rAF-throttled через redrawScheduled flag — устраняет potential jank при fast drag на медленном hardware (mousemove может fire'ить >60Hz).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-14 12:22:52 +03:00
parent 97da018724
commit bcdcca01a5
+13 -3
View File
@@ -1200,16 +1200,26 @@ document.getElementById('btn-clear').addEventListener('click', () => {
const LEGEND_STORAGE_KEY = 'liderra-map-legend-width';
const LEGEND_MIN_W = 300, LEGEND_MAX_W = 900;
let redrawScheduled = false;
function applyLegendWidth(w) {
const clamped = Math.max(LEGEND_MIN_W, Math.min(LEGEND_MAX_W, w));
const panel = document.getElementById('legend-panel');
panel.style.width = clamped + 'px';
panel.style.minWidth = clamped + 'px';
if (typeof network !== 'undefined' && network) network.redraw();
if (typeof network !== 'undefined' && network && !redrawScheduled) {
redrawScheduled = true;
requestAnimationFrame(() => {
redrawScheduled = false;
network.redraw();
});
}
}
function restoreLegendWidth() {
const saved = parseInt(localStorage.getItem(LEGEND_STORAGE_KEY) || '300', 10);
let saved = 300;
try {
saved = parseInt(localStorage.getItem(LEGEND_STORAGE_KEY) || '300', 10);
} catch (e) { /* private mode or quota — keep default */ }
applyLegendWidth(saved);
}
@@ -1234,7 +1244,7 @@ function restoreLegendWidth() {
handle.classList.remove('dragging');
document.body.style.userSelect = '';
const w = parseInt(document.getElementById('legend-panel').style.width, 10);
localStorage.setItem(LEGEND_STORAGE_KEY, String(w));
try { localStorage.setItem(LEGEND_STORAGE_KEY, String(w)); } catch (e) { /* private mode or quota */ }
});
})();