feat: add automatic waveform repaint on theme change

Implemented MutationObserver to detect theme changes:

- Added themeKey state that increments on theme change
- MutationObserver watches document.documentElement for class changes
- Detects when "dark" class is toggled
- Added themeKey to waveform effect dependencies
- Canvas automatically redraws with new theme colors

How it works:
1. Observer listens for class attribute changes on <html>
2. When dark mode is toggled, themeKey increments
3. useEffect dependency triggers canvas redraw
4. getComputedStyle reads fresh --color-waveform-bg value
5. Waveform renders with correct theme background

Benefits:
- Seamless theme transitions
- Waveform colors always match current theme
- No manual refresh needed
- Automatic cleanup on unmount

Now switching between light/dark themes instantly updates
all waveform backgrounds with the correct theme colors!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-18 08:36:49 +01:00
parent 2a0d6cd673
commit ee24f04d76

View File

@@ -58,6 +58,7 @@ export function Track({
const [nameInput, setNameInput] = React.useState(String(track.name || 'Untitled Track'));
const [effectBrowserOpen, setEffectBrowserOpen] = React.useState(false);
const [showEffects, setShowEffects] = React.useState(false);
const [themeKey, setThemeKey] = React.useState(0);
const inputRef = React.useRef<HTMLInputElement>(null);
const handleNameClick = () => {
@@ -90,6 +91,22 @@ export function Track({
}
}, [isEditingName]);
// Listen for theme changes
React.useEffect(() => {
const observer = new MutationObserver(() => {
// Increment key to force waveform redraw
setThemeKey((prev) => prev + 1);
});
// Watch for class changes on document element (dark mode toggle)
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class'],
});
return () => observer.disconnect();
}, []);
// Draw waveform
React.useEffect(() => {
if (!track.audioBuffer || !canvasRef.current) return;
@@ -166,7 +183,7 @@ export function Track({
ctx.lineTo(playheadX, height);
ctx.stroke();
}
}, [track.audioBuffer, track.color, track.collapsed, track.height, zoom, currentTime, duration]);
}, [track.audioBuffer, track.color, track.collapsed, track.height, zoom, currentTime, duration, themeKey]);
const handleCanvasClick = (e: React.MouseEvent<HTMLCanvasElement>) => {
if (!onSeek || !duration) return;