Avoid vis being needlessly destroyed (pledit still does this)

This commit is contained in:
Eris Lund 2026-06-02 21:15:03 +02:00
parent b382843693
commit ee7c90c81e
2 changed files with 42 additions and 19 deletions

View file

@ -54,10 +54,10 @@ export default function Vis({ analyser }: Props) {
const audioStatus = useTypedSelector(Selectors.getMediaStatus);
const getWindowShade = useTypedSelector(Selectors.getWindowShade);
const getWindowOpen = useTypedSelector(Selectors.getWindowOpen);
const isMWOpen = getWindowOpen("main");
const isMWOpen = getWindowOpen("main") ?? false;
const doubled = useTypedSelector(Selectors.getDoubled);
const toggleVisualizerStyle = useActionCreator(Actions.toggleVisualizerStyle);
const windowShade = getWindowShade("main");
const windowShade = getWindowShade("main") ?? false;
const smallVis = windowShade && isMWOpen;
const renderHeight = smallVis ? 5 : 16;
@ -81,16 +81,17 @@ export default function Vis({ analyser }: Props) {
//? painter administration
const painter = useMemo(() => {
if (!canvas) return null;
const modeValue: "bars" | "oscilloscope" | "none" =
mode === VISUALIZERS.BAR
? "bars"
: mode === VISUALIZERS.OSCILLOSCOPE
? "oscilloscope"
: "none";
const cfg = {
canvas,
analyser,
colors,
mode:
mode === VISUALIZERS.BAR
? "bars"
: mode === VISUALIZERS.OSCILLOSCOPE
? "oscilloscope"
: "none",
mode: modeValue,
renderHeight,
smallVis,
pixelDensity,
@ -99,7 +100,7 @@ export default function Vis({ analyser }: Props) {
peaks: true,
oscStyle: "lines",
bandwidth: "wide",
coloring: "normal",
coloring: "line",
};
return createVisualizerEngine(cfg);
}, [
@ -107,12 +108,6 @@ export default function Vis({ analyser }: Props) {
canvas,
mode,
colors,
renderHeight,
smallVis,
pixelDensity,
doubled,
isMWOpen,
smallVis,
]);
// reacts to changes in doublesize mode
@ -133,6 +128,18 @@ export default function Vis({ analyser }: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [doubled, canvas, painter]);
// updates painter configuration when layout changes (windowShade, main window open/closed)
// without recreating the painter, preserving visualizer state
useEffect(() => {
if (painter) {
painter.updateConfig({
doubled,
isMWOpen,
smallVis,
});
}
}, [doubled, isMWOpen, smallVis, painter]);
useEffect(() => {
if (canvas == null || painter == null) {
return;

View file

@ -48,8 +48,8 @@ export function createVisualizerEngine(cfg: VEConfig) {
const INITIAL_KICK_OFF = 3.0;
const doubleSized = !!cfg.doubled;
const isMWOpen = !!cfg.isMWOpen;
let doubleSized = !!cfg.doubled;
let isMWOpen = !!cfg.isMWOpen;
const visMode =
cfg.mode === "oscilloscope" ? 1 : cfg.mode === "bars" ? 0 : -1;
const visOscStyle =
@ -61,7 +61,7 @@ export function createVisualizerEngine(cfg: VEConfig) {
? 2
: 0;
const saColorMode = coloring === "normal" ? 0 : coloring === "fire" ? 1 : 2;
const windowShaded = smallVis;
let windowShaded = smallVis;
const peaks = !!cfg.peaks;
const wideBars = cfg.bandwidth === "wide" ? 1 : 0;
@ -783,5 +783,21 @@ export function createVisualizerEngine(cfg: VEConfig) {
ctx.putImageData(myImageData, 0, 0);
}
return { prepare, paintFrame };
function updateConfig(newCfg: Partial<VEConfig>) {
// Update mutable configuration values that can change without recreating the painter
if (newCfg.doubled !== undefined) {
doubleSized = !!newCfg.doubled;
prepare(); // recalculate buffer size
}
if (newCfg.isMWOpen !== undefined) {
isMWOpen = !!newCfg.isMWOpen;
prepare(); // recalculate buffer size
}
if (newCfg.smallVis !== undefined) {
windowShaded = !!newCfg.smallVis;
prepare(); // recalculate buffer size
}
}
return { prepare, paintFrame, updateConfig };
}