Files
ai.interactive.fiction/public/js/animation-queue.js
T

212 lines
6.2 KiB
JavaScript

/**
* Animation Queue Module
* Handles scheduling and executing animations with proper resource management
* and synchronization with TTS
*/
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 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 {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: () => {
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();
// Remove from queue
const index = this.queue.indexOf(timeoutObject);
if (index !== -1) {
this.queue.splice(index, 1);
}
}, adjustedDelay);
// Add to queue
this.queue.push(timeoutObject);
// Update current total delay
this.delay = adjustedDelay + delay;
return timeoutObject;
}
/**
* Fast-forward all pending animations
*/
fastForward() {
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 = [];
// Reset delay
this.delay = 0;
// Use direct DOM event dispatch instead of this.dispatchEvent
document.dispatchEvent(new CustomEvent('animations:fastForwarded', {
detail: { moduleId: this.id }
}));
}
/**
* Clear all scheduled animations without executing them
*/
clearAll() {
console.log(`Animation Queue: Clearing ${this.queue.length} pending items`);
// Clear all timeouts
this.queue.forEach(timeoutObject => {
if (timeoutObject.timeoutId !== null) {
clearTimeout(timeoutObject.timeoutId);
}
});
// Clear queue
this.queue = [];
// Reset delay
this.delay = 0;
}
/**
* Set the animation speed
* @param {number} speed - Animation speed factor (lower is faster)
*/
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 current queue length
* @returns {number} - Number of items in the queue
*/
getQueueLength() {
return this.queue.length;
}
/**
* Get current accumulated delay
* @returns {number} - Current delay in milliseconds
*/
getCurrentDelay() {
return this.delay;
}
}
// 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;