Split everything up into dynamically loaded modules.

This commit is contained in:
2025-04-04 00:00:43 +00:00
parent 2f7cda4b6d
commit aa29a6fd93
32 changed files with 8768 additions and 3935 deletions
+171 -77
View File
@@ -1,117 +1,211 @@
/**
* AnimationQueue Module
* Manages the timing and execution queue for all scheduled animations (primarily text reveal).
* Animation Queue Module
* Handles scheduling and executing animations with proper resource management
* and synchronization with TTS
*/
export class AnimationQueue {
constructor() {
this.queue = [];
this.delay = 0;
this.speed = 0.05; // Default speed
}
import { BaseModule } from './base-module.js';
import { moduleRegistry } from './module-registry.js';
import { ModuleEvent } from './base-module.js'; // Add this import
class AnimationQueueModule extends BaseModule {
constructor() {
super('animation-queue', 'Animation Queue');
// Queue of scheduled animations/functions
this.queue = [];
// Animation timing properties
this.speed = 0.05; // Base animation speed (seconds per character)
this.delay = 0; // Current accumulated delay
// Module dependencies
this.dependencies = ['tts'];
this.tts = null; // TTS module reference
// Fast-forwarding state
this.isFastForwarding = false;
// Bind methods
this.schedule = this.schedule.bind(this);
this.fastForward = this.fastForward.bind(this);
this.clearAll = this.clearAll.bind(this);
this.setSpeed = this.setSpeed.bind(this);
}
async waitForDependencies() {
try {
// Wait for TTS module to be available
this.tts = moduleRegistry.getModule('tts');
if (!this.tts) {
console.warn("TTS module not ready, Animation Queue will have limited functionality");
return true; // Continue anyway
}
return true;
} catch (error) {
console.error("Error waiting for Animation Queue dependencies:", error);
return false;
}
}
async initialize() {
try {
// Nothing special to initialize here
this.reportProgress(100, "Animation Queue ready");
return true;
} catch (error) {
console.error("Error initializing Animation Queue:", error);
return false;
}
}
/**
* Schedule a function to be executed after a delay
* @param {Function} func - The function to execute
* @param {number} delay - The delay in milliseconds
* Schedule a function to execute after a delay
* @param {Function} func - Function to execute
* @param {number} delay - Delay in milliseconds
* @param {...any} args - Arguments to pass to the function
* @returns {number} The timeout ID
* @returns {Object} - Timeout object that can be used to cancel
*/
schedule(func, delay, ...args) {
if (typeof func !== 'function') {
console.error('Animation Queue: Not a function passed to schedule');
return null;
}
// Create timeout object with execute method
const timeoutObject = {
execute: () => func(...args),
timeoutId: null
execute: () => {
try {
func(...args);
} catch (error) {
console.error('Error executing scheduled function:', error);
}
},
timeoutId: null,
createdAt: Date.now(),
delay: delay
};
// Apply speed factor to the delay
const adjustedDelay = delay * this.speed;
// Schedule execution
timeoutObject.timeoutId = setTimeout(() => {
// Execute the function
timeoutObject.execute();
this.queue = this.queue.filter(t => t !== timeoutObject);
if (this.queue.length <= 0) {
let event = new CustomEvent("allWordsSetEvent", {
detail: { messages: "All scheduled word fade in animations were played." },
bubbles: true,
cancelable: false
});
document.dispatchEvent(event);
// Remove from queue
const index = this.queue.indexOf(timeoutObject);
if (index !== -1) {
this.queue.splice(index, 1);
}
}, delay);
}, adjustedDelay);
// Add to queue
this.queue.push(timeoutObject);
return timeoutObject.timeoutId;
// Update current total delay
this.delay = adjustedDelay + delay;
return timeoutObject;
}
/**
* Fast forward all scheduled animations
* Fast-forward all pending animations
*/
fastForward() {
this.delay = 0.0;
// Sort the queue based on timeoutId (assuming that smaller ids are scheduled earlier)
this.queue.sort((a, b) => a.timeoutId - b.timeoutId);
// Clear and execute all timeouts
this.queue.forEach(timeoutObject => {
clearTimeout(timeoutObject.timeoutId);
console.log(`Animation Queue: Fast-forwarding ${this.queue.length} pending items`);
// Stop TTS if playing
if (this.tts) {
this.tts.stop();
}
// Execute and clear all timeouts
const queueCopy = [...this.queue]; // Make a copy to avoid modification during iteration
queueCopy.forEach(timeoutObject => {
// Clear timeout
if (timeoutObject.timeoutId !== null) {
clearTimeout(timeoutObject.timeoutId);
}
// Execute immediately
timeoutObject.execute();
});
// Clear queue
this.queue = [];
let event = new CustomEvent("allWordsSetEvent", {
detail: { messages: "All scheduled word fade in animations were played." },
bubbles: true,
cancelable: false
});
document.dispatchEvent(event);
document.getElementById("page_right").scrollTo({
top: document.getElementById("page_right").scrollHeight,
behavior: 'smooth'
});
// Reset delay
this.delay = 0;
// Use direct DOM event dispatch instead of this.dispatchEvent
document.dispatchEvent(new CustomEvent('animations:fastForwarded', {
detail: { moduleId: this.id }
}));
}
/**
* Stop all scheduled animations
* Clear all scheduled animations without executing them
*/
stop() {
clearAll() {
console.log(`Animation Queue: Clearing ${this.queue.length} pending items`);
// Clear all timeouts
this.queue.forEach(timeoutObject => {
clearTimeout(timeoutObject.timeoutId);
if (timeoutObject.timeoutId !== null) {
clearTimeout(timeoutObject.timeoutId);
}
});
// Clear queue
this.queue = [];
// Reset delay
this.delay = 0;
}
/**
* Set the animation speed
* @param {number} value - The speed value
* @param {number} speed - Animation speed factor (lower is faster)
*/
setSpeed(value) {
this.speed = value;
setSpeed(speed) {
if (typeof speed !== 'number' || speed <= 0) {
console.error('Animation Queue: Invalid speed value');
return;
}
this.speed = speed;
console.log(`Animation Queue: Speed set to ${speed}`);
}
/**
* Get the current animation speed
* @returns {number} The current speed
* Get current queue length
* @returns {number} - Number of items in the queue
*/
getSpeed() {
return this.speed;
getQueueLength() {
return this.queue.length;
}
/**
* Get the current accumulated delay
* @returns {number} The current delay
* Get current accumulated delay
* @returns {number} - Current delay in milliseconds
*/
getDelay() {
getCurrentDelay() {
return this.delay;
}
/**
* Set the accumulated delay
* @param {number} value - The delay value
*/
setDelay(value) {
this.delay = value;
}
/**
* Increment the accumulated delay
* @param {number} value - The amount to increment
*/
incrementDelay(value) {
this.delay += value;
}
}
// Create the singleton instance
const AnimationQueue = new AnimationQueueModule();
// Register with the module registry
moduleRegistry.register(AnimationQueue);
// Export the module
export { AnimationQueue };
// Keep a reference in window for loader system
window.AnimationQueue = AnimationQueue;