Split everything up into dynamically loaded modules.
This commit is contained in:
+171
-77
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user