From c19dbcf52aa955da73f12092d4822ebe038c7f5d Mon Sep 17 00:00:00 2001 From: Daniel <790119+DanTheMan827@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:34:58 -0500 Subject: [PATCH] refactor: adjust imports to allow for file splitting - dynamically import router - dynamically import visualizers - update import syntax for am-lyrics to use dynamic import syntax --- js/commandPalette.js | 8 ++++---- js/lyrics.js | 2 +- js/settings.js | 44 ++++++++++++++++++++++++-------------------- js/ui.js | 11 ++++++----- js/visualizer.js | 31 ++++++++++++++----------------- 5 files changed, 49 insertions(+), 47 deletions(-) diff --git a/js/commandPalette.js b/js/commandPalette.js index fef1b84..154f477 100644 --- a/js/commandPalette.js +++ b/js/commandPalette.js @@ -1,6 +1,7 @@ import { debounce } from './utils.js'; import { db } from './db.js'; import Fuse from 'fuse.js'; +import { navigate } from './router.js'; class CommandPalette { constructor() { @@ -368,7 +369,7 @@ class CommandPalette { description: `Navigate to ${p}`, action: () => { this.close(); - import('./router.js').then((m) => m.navigate(p === 'home' ? '/' : `/${p}`)); + navigate(p === 'home' ? '/' : `/${p}`); }, type: 'command', })) @@ -380,7 +381,7 @@ class CommandPalette { if (validPages.includes(page)) { this.close(); - import('./router.js').then((m) => m.navigate(page === 'home' ? '/' : `/${page}`)); + navigate(page === 'home' ? '/' : `/${page}`); } else { this.showNotification(`Unknown page: ${page}`); } @@ -673,8 +674,7 @@ class CommandPalette { } async navigateToSetting(setting) { - const router = await import('./router.js'); - router.navigate('/settings'); + navigate('/settings'); await new Promise((resolve) => setTimeout(resolve, 100)); diff --git a/js/lyrics.js b/js/lyrics.js index dfbc81a..b5d5378 100644 --- a/js/lyrics.js +++ b/js/lyrics.js @@ -10,7 +10,7 @@ import { SVG_GLOBE, } from './icons.js'; import { sidePanelManager } from './side-panel.js'; -import '@uimaxbai/am-lyrics/am-lyrics.js'; +import('@uimaxbai/am-lyrics/am-lyrics.js'); // Check if text contains Japanese, Chinese, or Korean characters function containsAsianText(text) { diff --git a/js/settings.js b/js/settings.js index 41cac78..e43c0fa 100644 --- a/js/settings.js +++ b/js/settings.js @@ -37,12 +37,16 @@ import { modalSettings, } from './storage.js'; import { audioContextManager, EQ_PRESETS } from './audio-context.js'; -import { getButterchurnPresets } from './visualizers/butterchurn.js'; import { db } from './db.js'; import { authManager } from './accounts/auth.js'; import { syncManager } from './accounts/pocketbase.js'; import { containerFormats, customFormats } from './ffmpegFormats.ts'; +async function getButterchurnPresets(...args) { + const butterchurnModule = await import('./visualizers/butterchurn.js'); + return butterchurnModule.getButterchurnPresets(...args); +} + export function initializeSettings(scrobbler, player, api, ui) { // Restore last active settings tab const savedTab = settingsUiState.getActiveTab(); @@ -2311,7 +2315,7 @@ export function initializeSettings(scrobbler, player, api, ui) { const butterchurnDurationInput = document.getElementById('butterchurn-duration-input'); const butterchurnRandomizeToggle = document.getElementById('butterchurn-randomize-toggle'); - const updateButterchurnSettingsVisibility = () => { + const updateButterchurnSettingsVisibility = async () => { const isEnabled = visualizerEnabledToggle ? visualizerEnabledToggle.checked : false; const isButterchurn = visualizerPresetSelect ? visualizerPresetSelect.value === 'butterchurn' : false; const show = isEnabled && isButterchurn; @@ -2327,7 +2331,7 @@ export function initializeSettings(scrobbler, player, api, ui) { if (butterchurnRandomizeSetting) butterchurnRandomizeSetting.style.display = showSubSettings ? 'flex' : 'none'; // Populate preset list using module-level cache (works even before visualizer initializes) - const { keys: presetNames } = getButterchurnPresets(); + const { keys: presetNames } = await getButterchurnPresets(); const select = butterchurnSpecificPresetSelect; if (select && presetNames.length > 0) { @@ -2362,7 +2366,7 @@ export function initializeSettings(scrobbler, player, api, ui) { } }; - const updateVisualizerSettingsVisibility = (enabled) => { + const updateVisualizerSettingsVisibility = async (enabled) => { const display = enabled ? 'flex' : 'none'; if (visualizerModeSetting) visualizerModeSetting.style.display = display; if (visualizerSmartIntensitySetting) visualizerSmartIntensitySetting.style.display = display; @@ -2370,7 +2374,7 @@ export function initializeSettings(scrobbler, player, api, ui) { if (visualizerPresetSetting) visualizerPresetSetting.style.display = display; // Also update Butterchurn specific visibility - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }; // Initialize preset select value early so visibility logic works correctly on load @@ -2381,24 +2385,24 @@ export function initializeSettings(scrobbler, player, api, ui) { if (visualizerEnabledToggle) { visualizerEnabledToggle.checked = visualizerSettings.isEnabled(); - updateVisualizerSettingsVisibility(visualizerEnabledToggle.checked); + await updateVisualizerSettingsVisibility(visualizerEnabledToggle.checked); - visualizerEnabledToggle.addEventListener('change', (e) => { + visualizerEnabledToggle.addEventListener('change', async (e) => { visualizerSettings.setEnabled(e.target.checked); - updateVisualizerSettingsVisibility(e.target.checked); + await updateVisualizerSettingsVisibility(e.target.checked); }); } // Visualizer Preset Select if (visualizerPresetSelect) { // value set above - visualizerPresetSelect.addEventListener('change', (e) => { + visualizerPresetSelect.addEventListener('change', async (e) => { const val = e.target.value; visualizerSettings.setPreset(val); if (ui && ui.visualizer) { ui.visualizer.setPreset(val); } - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); //Since changing the preset breaks the visualizer, a location.reload() is added to make sure that it works window.location.reload(); @@ -2407,9 +2411,9 @@ export function initializeSettings(scrobbler, player, api, ui) { if (butterchurnCycleToggle) { butterchurnCycleToggle.checked = visualizerSettings.isButterchurnCycleEnabled(); - butterchurnCycleToggle.addEventListener('change', (e) => { + butterchurnCycleToggle.addEventListener('change', async (e) => { visualizerSettings.setButterchurnCycleEnabled(e.target.checked); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }); } @@ -2441,30 +2445,30 @@ export function initializeSettings(scrobbler, player, api, ui) { } // Refresh settings when presets are loaded asynchronously - window.addEventListener('butterchurn-presets-loaded', () => { + window.addEventListener('butterchurn-presets-loaded', async () => { console.log('[Settings] Butterchurn presets loaded event received'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); }); // Check if presets already cached and update immediately - const { keys: cachedKeys } = getButterchurnPresets(); + const { keys: cachedKeys } = await getButterchurnPresets(); if (cachedKeys.length > 0) { console.log('[Settings] Presets already cached, updating dropdown immediately'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); } // Watch for appearance tab becoming active and refresh presets const appearanceTabContent = document.getElementById('settings-tab-appearance'); if (appearanceTabContent) { - const observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { + const observer = new MutationObserver(async (mutations) => { + for (const mutation of mutations) { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { if (appearanceTabContent.classList.contains('active')) { console.log('[Settings] Appearance tab became active, refreshing presets'); - updateButterchurnSettingsVisibility(); + await updateButterchurnSettingsVisibility(); } } - }); + } }); observer.observe(appearanceTabContent, { attributes: true }); } diff --git a/js/ui.js b/js/ui.js index be136c5..0f625ab 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1126,7 +1126,7 @@ export class UIRenderer { overlay.style.display = 'flex'; - const startVisualizer = () => { + const startVisualizer = async () => { if (!visualizerSettings.isEnabled()) { if (this.visualizer) this.visualizer.stop(); return; @@ -1136,6 +1136,7 @@ export class UIRenderer { const canvas = document.getElementById('visualizer-canvas'); if (canvas) { this.visualizer = new Visualizer(canvas, activeElement); + await this.visualizer.initPresets(); } } if (this.visualizer) { @@ -1150,7 +1151,7 @@ export class UIRenderer { this.setupUIToggleButton(overlay); if (localStorage.getItem('epilepsy-warning-dismissed') === 'true') { - startVisualizer(); + await startVisualizer(); } else { const modal = document.getElementById('epilepsy-warning-modal'); if (modal) { @@ -1159,17 +1160,17 @@ export class UIRenderer { const acceptBtn = document.getElementById('epilepsy-accept-btn'); const cancelBtn = document.getElementById('epilepsy-cancel-btn'); - acceptBtn.onclick = () => { + acceptBtn.onclick = async () => { modal.classList.remove('active'); localStorage.setItem('epilepsy-warning-dismissed', 'true'); - startVisualizer(); + await startVisualizer(); }; cancelBtn.onclick = () => { modal.classList.remove('active'); this.closeFullscreenCover(); }; } else { - startVisualizer(); + await startVisualizer(); } } } diff --git a/js/visualizer.js b/js/visualizer.js index 2e58dae..5cfdc2f 100644 --- a/js/visualizer.js +++ b/js/visualizer.js @@ -1,10 +1,5 @@ // js/visualizer.js import { visualizerSettings } from './storage.js'; -import { LCDPreset } from './visualizers/lcd.js'; -import { ParticlesPreset } from './visualizers/particles.js'; -import { UnknownPleasuresWebGL } from './visualizers/unknown_pleasures_webgl.js'; -import { ButterchurnPreset } from './visualizers/butterchurn.js'; -import { KawarpPreset } from './visualizers/kawarp.js'; import { audioContextManager } from './audio-context.js'; export class Visualizer { @@ -12,21 +7,10 @@ export class Visualizer { this.canvas = canvas; this.ctx = null; this.audio = audio; - this.audioContext = null; this.analyser = null; - this.isActive = false; this.animationId = null; - - this.presets = { - lcd: new LCDPreset(), - particles: new ParticlesPreset(), - 'unknown-pleasures': new UnknownPleasuresWebGL(), - butterchurn: new ButterchurnPreset(), - kawarp: new KawarpPreset(), - }; - this.activePresetKey = visualizerSettings.getPreset(); // ---- AUDIO BUFFERS (REUSED) ---- @@ -51,6 +35,19 @@ export class Visualizer { this._resizeBound = () => this.resize(); } + /** + * Must be called after class is constructed! + */ + async initPresets() { + this.presets = { + lcd: new (await import('./visualizers/lcd.js')).LCDPreset(), + particles: new (await import('./visualizers/particles.js')).ParticlesPreset(), + 'unknown-pleasures': new (await import('./visualizers/unknown_pleasures_webgl.js')).UnknownPleasuresWebGL(), + butterchurn: new (await import('./visualizers/butterchurn.js')).ButterchurnPreset(), + kawarp: new (await import('./visualizers/kawarp.js')).KawarpPreset(), + }; + } + updateDimming() { if (!this.canvas || !this.canvas.parentElement) return; const dimAmount = visualizerSettings.getDimAmount(); @@ -61,7 +58,7 @@ export class Visualizer { return this.presets[this.activePresetKey] || this.presets['lcd']; } - init() { + async init() { // Ensure shared audio context is initialized if (!audioContextManager.isReady()) { audioContextManager.init(this.audio);