more cleaning up

This commit is contained in:
Andras Schmelczer 2026-05-16 20:45:42 +01:00
commit 560398fefb
110 changed files with 931 additions and 2645 deletions

View file

@ -2,12 +2,7 @@ import GameLoop from './game-loop/game-loop';
import './index.scss';
import {
initAnalytics,
trackExport,
trackSettingsOpen,
trackVibeChange,
} from './analytics';
import { initAnalytics, trackExport, trackVibeChange } from './analytics';
import { preloadPianoSamples } from './audio/piano-samples';
import { appConfig } from './config';
import { CollapsiblePanelAnimator } from './page/collapsible-panel-animator';
@ -131,7 +126,6 @@ const queryAppElements = () => ({
export4k: queryRequiredElement('.export-4k', HTMLButtonElement),
exportStatus: queryRequiredElement('.export-status', HTMLSpanElement),
prompt: queryRequiredElement('.garden-prompt', HTMLDivElement),
loadingIndicator: queryRequiredElement('.loading-indicator', HTMLDivElement),
loadingStatus: queryRequiredElement('.loading-status', HTMLDivElement),
loadingProgress: queryRequiredElement('.loading-progress', HTMLDivElement),
});
@ -143,11 +137,12 @@ let elements: AppElements;
const setLoadingStage = (label: string, ratio: number) => {
const percent = Math.round(Math.max(0, Math.min(1, ratio)) * 100);
elements.loadingStatus.textContent = label;
elements.loadingIndicator.style.setProperty('--loading-progress', `${percent}%`);
elements.loadingProgress.style.setProperty('--loading-progress', `${percent}%`);
elements.loadingProgress.setAttribute('aria-valuenow', String(percent));
};
let isAudioMuted = readBrowserStorage(appConfig.storage.audioMutedKey) === '1';
let isEraserActive = false;
const renderAudioUi = (game: GameLoop | null) => {
elements.soundButton.classList.toggle('muted', isAudioMuted);
@ -161,21 +156,19 @@ const renderAudioUi = (game: GameLoop | null) => {
};
const renderPaletteUi = (game: GameLoop | null) => {
const isErasing = elements.eraserSizeControl.dataset.active === '1';
elements.swatches.forEach((swatch, index) => {
swatch.style.backgroundColor = activeVibe.colors[index];
swatch.classList.toggle(
'active',
settings.selectedColorIndex === index && !isErasing
settings.selectedColorIndex === index && !isEraserActive
);
});
elements.eraserSizeControl.classList.toggle('active', isErasing);
game?.setEraseMode(isErasing);
elements.eraserSizeControl.classList.toggle('active', isEraserActive);
game?.setEraseMode(isEraserActive);
document.documentElement.style.setProperty(
'--garden-background',
activeVibe.backgroundColor
);
game?.onVibeChanged();
};
const renderEraserSizeUi = (game: GameLoop | null) => {
@ -234,11 +227,11 @@ const main = async () => {
let shouldStop = false;
let game: GameLoop | null = null;
let wasConfigPaneOpen = false;
let configPane: ConfigPane | null = null;
elements = queryAppElements();
elements.errorContainer.setAttribute('aria-live', 'assertive');
ErrorHandler.addOnErrorListener((error, _metadata) => {
ErrorHandler.addOnErrorListener((error) => {
renderRuntimeMessage(elements.errorContainer, error);
if (error.severity === Severity.ERROR) {
document.body.classList.remove('is-loading');
@ -248,10 +241,10 @@ const main = async () => {
});
hasRuntimeErrorListener = true;
const syncRuntimeUi = () => {
const syncRuntimeUi = (activeGame = game) => {
renderEraserSizeUi(game);
renderMirrorSegmentUi();
renderPaletteUi(game);
renderPaletteUi(activeGame);
};
const infoPageHandler = new CollapsiblePanelAnimator(
@ -259,29 +252,33 @@ const main = async () => {
elements.infoElement,
elements.aside
);
const configPane = new ConfigPane({
configPane = new ConfigPane({
settingsButton: elements.settingsButton,
onConfigChange: syncRuntimeUi,
onOpenChange: (isOpen) => {
game?.setStatsOverlayPinned(isOpen);
if (isOpen && !wasConfigPaneOpen) {
trackSettingsOpen();
}
wasConfigPaneOpen = isOpen;
onConfigChange: () => {
game?.onVibeChanged();
syncRuntimeUi();
},
onOpenChange: () => undefined,
onRuntimeChange: syncRuntimeUi,
onRuntimeReset: () => {
resetSettings();
game?.onVibeChanged();
syncRuntimeUi();
},
onRestart: () => game?.destroy(),
onVibeChange: (vibeId) => {
const vibe = applyVibeSettings(vibeId);
const vibe = VIBE_PRESETS.find((candidate) => candidate.id === vibeId);
if (!vibe) {
return;
}
const activePreset = applyVibeSettings(vibe);
trackVibeChange({
vibeId: vibe.id,
vibeName: vibe.name,
vibeId: activePreset.id,
vibeName: activePreset.name,
source: 'settings',
});
game?.onVibeChanged();
syncRuntimeUi();
game?.playVibeChangeAudio(false);
},
@ -292,7 +289,7 @@ const main = async () => {
elements.aside,
() =>
FullScreenHandler.isInFullScreenMode() &&
!configPane.isOpen &&
!configPane?.isOpen &&
!infoPageHandler.isOpen
);
new FullScreenHandler(
@ -333,47 +330,41 @@ const main = async () => {
}
});
elements.previousVibe.addEventListener('click', () => {
const selectRelativeVibe = (offset: number, source: string) => {
const current = VIBE_PRESETS.findIndex((vibe) => vibe.id === activeVibe.id);
const vibe =
VIBE_PRESETS[(current + VIBE_PRESETS.length - 1) % VIBE_PRESETS.length];
const activePreset = applyVibeSettings(vibe.id);
VIBE_PRESETS[(current + VIBE_PRESETS.length + offset) % VIBE_PRESETS.length];
const activePreset = applyVibeSettings(vibe);
trackVibeChange({
vibeId: activePreset.id,
vibeName: activePreset.name,
source: 'previous-button',
source,
});
configPane.refresh();
game?.onVibeChanged();
syncRuntimeUi();
configPane?.refresh();
game?.playVibeChangeAudio(true);
});
};
elements.nextVibe.addEventListener('click', () => {
const current = VIBE_PRESETS.findIndex((vibe) => vibe.id === activeVibe.id);
const vibe = VIBE_PRESETS[(current + 1) % VIBE_PRESETS.length];
const activePreset = applyVibeSettings(vibe.id);
trackVibeChange({
vibeId: activePreset.id,
vibeName: activePreset.name,
source: 'next-button',
});
configPane.refresh();
syncRuntimeUi();
game?.playVibeChangeAudio(true);
});
elements.previousVibe.addEventListener('click', () =>
selectRelativeVibe(-1, 'previous-button')
);
elements.nextVibe.addEventListener('click', () =>
selectRelativeVibe(1, 'next-button')
);
elements.swatches.forEach((swatch, index) => {
swatch.addEventListener('click', () => {
settings.selectedColorIndex = index;
elements.eraserSizeControl.dataset.active = '0';
game?.setEraseMode(false);
isEraserActive = false;
renderPaletteUi(game);
configPane.refresh();
configPane?.refresh();
});
});
const activateEraser = () => {
elements.eraserSizeControl.dataset.active = '1';
isEraserActive = true;
renderPaletteUi(game);
};
@ -383,20 +374,20 @@ const main = async () => {
elements.eraserSizeSlider.addEventListener('input', () => {
settings.eraserSize = clampEraserSize(Number(elements.eraserSizeSlider.value));
elements.eraserSizeControl.dataset.active = '1';
isEraserActive = true;
renderEraserSizeUi(game);
renderPaletteUi(game);
configPane.refresh();
configPane?.refresh();
});
elements.mirrorSegmentSlider.addEventListener('input', () => {
settings.mirrorSegmentCount = clampMirrorSegmentCount(
Number(elements.mirrorSegmentSlider.value)
);
elements.eraserSizeControl.dataset.active = '0';
isEraserActive = false;
renderMirrorSegmentUi();
renderPaletteUi(game);
configPane.refresh();
configPane?.refresh();
});
elements.export4k.addEventListener('click', async () => {
@ -450,7 +441,6 @@ const main = async () => {
eraserPreview: elements.eraserPreview,
exportStatus: elements.exportStatus,
});
game.setStatsOverlayPinned(configPane.isOpen);
renderPaletteUi(game);
renderEraserSizeUi(game);
renderMirrorSegmentUi();