fix: Resolve light/dark theme issues across dashboards and settings

- Add missing setThemePreference() and setAnimationsEnabled() functions
  to settings-manager.js; sync theme/animations dropdowns in _updateUI
- Fix base.html toggleTheme() saving to wrong localStorage key ('theme'
  instead of 'intercept-theme'), causing theme not to persist in ADS-B
  and AIS dashboards; also sync button icon and persist to server
- Add [data-theme="light"] CSS variable overrides to adsb_dashboard.css
  and ais_dashboard.css so the dashboards respond to light theme
- Fix GPS sky view canvas (gps.js) to read grid/label colours from CSS
  variables instead of hardcoded dark hex values; add MutationObserver
  to redraw immediately on theme change
- Fix satellite_dashboard.html polar plot functions to read background,
  accent and text colours from CSS variables

Closes #139

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-02-18 13:58:49 +00:00
parent 4df112e712
commit 6c6cd8a280
6 changed files with 163 additions and 34 deletions

View File

@@ -609,11 +609,17 @@
const cy = canvas.height / 2;
const radius = Math.max(10, Math.min(cx, cy) - 40);
ctx.fillStyle = '#0a0a0f';
const cs = getComputedStyle(document.documentElement);
const bgColor = cs.getPropertyValue('--bg-card').trim() || '#0a0a0f';
const accentCyan = cs.getPropertyValue('--accent-cyan').trim() || '#00d4ff';
const accentRed = cs.getPropertyValue('--accent-red').trim() || '#ff4444';
const textDim = cs.getPropertyValue('--text-dim').trim() || 'rgba(0,212,255,0.4)';
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Elevation rings
ctx.strokeStyle = 'rgba(0, 212, 255, 0.15)';
ctx.strokeStyle = accentCyan + '26'; // ~15% opacity
ctx.lineWidth = 1;
for (let el = 30; el <= 90; el += 30) {
const r = radius * (1 - el / 90);
@@ -621,20 +627,20 @@
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.stroke();
ctx.fillStyle = 'rgba(0, 212, 255, 0.4)';
ctx.fillStyle = textDim;
ctx.font = '10px Roboto Condensed';
ctx.fillText(el + '°', cx + 5, cy - r + 12);
}
// Horizon
ctx.strokeStyle = 'rgba(0, 212, 255, 0.3)';
ctx.strokeStyle = accentCyan + '4D'; // ~30% opacity
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.stroke();
// Cardinal lines
ctx.strokeStyle = 'rgba(0, 212, 255, 0.1)';
ctx.strokeStyle = accentCyan + '1A'; // ~10% opacity
ctx.lineWidth = 1;
for (let az = 0; az < 360; az += 45) {
const angle = (az - 90) * Math.PI / 180;
@@ -647,10 +653,10 @@
// Cardinal labels
ctx.font = 'bold 14px Orbitron';
const labels = [
{ text: 'N', az: 0, color: '#ff4444' },
{ text: 'E', az: 90, color: '#00d4ff' },
{ text: 'S', az: 180, color: '#00d4ff' },
{ text: 'W', az: 270, color: '#00d4ff' }
{ text: 'N', az: 0, color: accentRed },
{ text: 'E', az: 90, color: accentCyan },
{ text: 'S', az: 180, color: accentCyan },
{ text: 'W', az: 270, color: accentCyan }
];
labels.forEach(l => {
const angle = (l.az - 90) * Math.PI / 180;
@@ -978,10 +984,18 @@
const cy = canvas.height / 2;
const radius = Math.max(10, Math.min(cx, cy) - 40);
ctx.fillStyle = '#0a0a0f';
const cs = getComputedStyle(document.documentElement);
const bgColor = cs.getPropertyValue('--bg-card').trim() || '#0a0a0f';
const accentCyan = cs.getPropertyValue('--accent-cyan').trim() || '#00d4ff';
const accentRed = cs.getPropertyValue('--accent-red').trim() || '#ff4444';
const accentGreen = cs.getPropertyValue('--accent-green').trim() || '#00ff88';
const textPrimary = cs.getPropertyValue('--text-primary').trim() || '#fff';
const textDim = cs.getPropertyValue('--text-dim').trim() || 'rgba(0,212,255,0.4)';
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'rgba(0, 212, 255, 0.15)';
ctx.strokeStyle = accentCyan + '26';
ctx.lineWidth = 1;
for (let elRing = 30; elRing <= 90; elRing += 30) {
const r = radius * (1 - elRing / 90);
@@ -989,18 +1003,18 @@
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.stroke();
ctx.fillStyle = 'rgba(0, 212, 255, 0.4)';
ctx.fillStyle = textDim;
ctx.font = '10px Roboto Condensed';
ctx.fillText(elRing + '°', cx + 5, cy - r + 12);
}
ctx.strokeStyle = 'rgba(0, 212, 255, 0.3)';
ctx.strokeStyle = accentCyan + '4D';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.stroke();
ctx.strokeStyle = 'rgba(0, 212, 255, 0.1)';
ctx.strokeStyle = accentCyan + '1A';
ctx.lineWidth = 1;
for (let azLine = 0; azLine < 360; azLine += 45) {
const angle = (azLine - 90) * Math.PI / 180;
@@ -1012,10 +1026,10 @@
ctx.font = 'bold 14px Orbitron';
const labels = [
{ text: 'N', az: 0, color: '#ff4444' },
{ text: 'E', az: 90, color: '#00d4ff' },
{ text: 'S', az: 180, color: '#00d4ff' },
{ text: 'W', az: 270, color: '#00d4ff' }
{ text: 'N', az: 0, color: accentRed },
{ text: 'E', az: 90, color: accentCyan },
{ text: 'S', az: 180, color: accentCyan },
{ text: 'W', az: 270, color: accentCyan }
];
labels.forEach(l => {
const angle = (l.az - 90) * Math.PI / 180;
@@ -1048,21 +1062,21 @@
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = '#fff';
ctx.strokeStyle = textPrimary;
ctx.lineWidth = 3;
ctx.stroke();
ctx.font = 'bold 11px Orbitron';
ctx.fillStyle = '#fff';
ctx.fillStyle = textPrimary;
ctx.textAlign = 'center';
ctx.fillText(satellites[selectedSatellite]?.name || 'SAT', x, y - 20);
ctx.font = '10px Roboto Condensed';
ctx.fillStyle = el > 0 ? '#00ff88' : '#ff4444';
ctx.fillStyle = el > 0 ? accentGreen : accentRed;
ctx.fillText(el.toFixed(1) + '°', x, y + 25);
} else {
ctx.font = '12px Rajdhani';
ctx.fillStyle = '#ff4444';
ctx.fillStyle = accentRed;
ctx.textAlign = 'center';
ctx.fillText('BELOW HORIZON', cx, cy + radius + 35);
}
@@ -1076,6 +1090,11 @@
const cy = canvas.height / 2;
const radius = Math.max(10, Math.min(cx, cy) - 40);
const cs = getComputedStyle(document.documentElement);
const accentRed = cs.getPropertyValue('--accent-red').trim() || '#ff4444';
const accentGreen = cs.getPropertyValue('--accent-green').trim() || '#00ff88';
const textPrimary = cs.getPropertyValue('--text-primary').trim() || '#fff';
if (el > -5) {
const posEl = Math.max(0, el);
const r = radius * (1 - posEl / 90);
@@ -1097,17 +1116,17 @@
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = '#fff';
ctx.strokeStyle = textPrimary;
ctx.lineWidth = 3;
ctx.stroke();
ctx.font = 'bold 11px Orbitron';
ctx.fillStyle = '#fff';
ctx.fillStyle = textPrimary;
ctx.textAlign = 'center';
ctx.fillText(satellites[selectedSatellite]?.name || 'SAT', x, y - 20);
ctx.font = '10px Roboto Condensed';
ctx.fillStyle = el > 0 ? '#00ff88' : '#ff4444';
ctx.fillStyle = el > 0 ? accentGreen : accentRed;
ctx.fillText(el.toFixed(1) + '°', x, y + 25);
}
}