Latest state before reworking with cluade 4.6.
This commit is contained in:
@@ -16,44 +16,21 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
this.pageLeft = null;
|
||||
this.pageRight = null;
|
||||
this.paragraphContainer = null;
|
||||
|
||||
// State
|
||||
this.currentParagraphId = 0;
|
||||
this.pendingParagraphs = [];
|
||||
|
||||
|
||||
// Resources to preload
|
||||
this.cssPath = '/css/style.css';
|
||||
this.imagesToPreload = [
|
||||
'/images/book-3057904.png',
|
||||
'/images/brown-wooden-flooring.jpg'
|
||||
];
|
||||
|
||||
// Configuration
|
||||
this.updateConfig({
|
||||
typography: {
|
||||
fontFamily: "'EB Garamond', serif",
|
||||
fontSize: '1.15rem',
|
||||
lineHeight: 1.5,
|
||||
maxWidth: 600
|
||||
},
|
||||
animation: {
|
||||
speed: 0.05, // Speed multiplier
|
||||
useTypingAnimation: true
|
||||
},
|
||||
display: {
|
||||
showChoices: true
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Bind methods using parent's bindMethods utility
|
||||
this.bindMethods([
|
||||
'initializeContainers',
|
||||
'displayText',
|
||||
'showChoices',
|
||||
'processNextParagraph',
|
||||
'measureText',
|
||||
'updateTypographySettings',
|
||||
'loadCSS',
|
||||
'showChoices',
|
||||
'preloadImages'
|
||||
]);
|
||||
|
||||
@@ -75,38 +52,16 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
this.paragraphLayout = this.getModule('paragraph-layout');
|
||||
this.layoutRenderer = this.getModule('layout-renderer');
|
||||
this.animationQueue = this.getModule('animation-queue');
|
||||
|
||||
if (!this.paragraphLayout) {
|
||||
console.error("UIDisplayHandler: Missing paragraph-layout module");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.layoutRenderer) {
|
||||
console.error("UIDisplayHandler: Missing layout-renderer module");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.animationQueue) {
|
||||
console.error("UIDisplayHandler: Missing animation-queue module");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
this.reportProgress(50, "Initializing display containers");
|
||||
|
||||
// Initialize container elements
|
||||
this.initializeContainers();
|
||||
|
||||
this.reportProgress(70, "Setting up typography");
|
||||
|
||||
// Set up measure function for paragraph layout
|
||||
const { fontSize, fontFamily } = this.config.typography;
|
||||
this.paragraphLayout.updateFont(fontSize, fontFamily);
|
||||
|
||||
|
||||
this.reportProgress(90, "Setting up event listeners");
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
|
||||
|
||||
this.reportProgress(100, "UI Display Handler ready");
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -114,25 +69,7 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up event listeners
|
||||
*/
|
||||
setupEventListeners() {
|
||||
// Listen for typography setting changes
|
||||
this.addEventListener(document, 'ui:typography:update', (event) => {
|
||||
if (event.detail) {
|
||||
this.updateTypographySettings(event.detail);
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for animation speed changes
|
||||
this.addEventListener(document, 'ui:animation:speed', (event) => {
|
||||
if (event.detail && typeof event.detail.speed === 'number') {
|
||||
this.config.animation.speed = event.detail.speed;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load CSS file asynchronously and wait for it to be applied
|
||||
@@ -141,16 +78,6 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
*/
|
||||
loadCSS(cssPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Check if the stylesheet is already loaded
|
||||
const existingLinks = document.querySelectorAll('link[rel="stylesheet"]');
|
||||
for (const link of existingLinks) {
|
||||
if (link.href.includes(cssPath)) {
|
||||
console.log(`UIDisplayHandler: CSS ${cssPath} already loaded`);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create link element
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
@@ -159,11 +86,7 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
// Set up load and error handlers
|
||||
link.onload = () => {
|
||||
console.log(`UIDisplayHandler: CSS ${cssPath} loaded successfully`);
|
||||
|
||||
// Give a small delay for the CSS to be applied
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 50);
|
||||
resolve();
|
||||
};
|
||||
|
||||
link.onerror = (error) => {
|
||||
@@ -347,49 +270,6 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
return this.context.measureText(text).width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update typography settings
|
||||
* @param {Object} settings - Typography settings
|
||||
*/
|
||||
updateTypographySettings(settings) {
|
||||
let changed = false;
|
||||
|
||||
if (settings.fontSize && settings.fontSize !== this.config.typography.fontSize) {
|
||||
this.config.typography.fontSize = settings.fontSize;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (settings.fontFamily && settings.fontFamily !== this.config.typography.fontFamily) {
|
||||
this.config.typography.fontFamily = settings.fontFamily;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (settings.lineHeight && settings.lineHeight !== this.config.typography.lineHeight) {
|
||||
this.config.typography.lineHeight = settings.lineHeight;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// If font settings changed, update the paragraph layout
|
||||
if (changed && this.paragraphLayout) {
|
||||
// Use the existing updateFont method
|
||||
this.paragraphLayout.updateFont(
|
||||
this.config.typography.fontSize,
|
||||
this.config.typography.fontFamily
|
||||
);
|
||||
|
||||
// Also update our local canvas context
|
||||
if (this.context) {
|
||||
this.context.font = `${this.config.typography.fontSize} ${this.config.typography.fontFamily}`;
|
||||
}
|
||||
|
||||
// Dispatch event about typography changes
|
||||
this.dispatchEvent('ui:font:change', {
|
||||
fontSize: this.config.typography.fontSize,
|
||||
fontFamily: this.config.typography.fontFamily,
|
||||
lineHeight: this.config.typography.lineHeight
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display text in the UI
|
||||
@@ -421,83 +301,6 @@ class UIDisplayHandlerModule extends BaseModule {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the next paragraph in the queue
|
||||
*/
|
||||
processNextParagraph() {
|
||||
if (this.pendingParagraphs.length === 0) return;
|
||||
|
||||
const paragraph = this.pendingParagraphs[0];
|
||||
const { id, text, options, resolve } = paragraph;
|
||||
|
||||
try {
|
||||
// Use the paragraph layout to calculate the optimal layout
|
||||
const layout = this.paragraphLayout.calculateLayout(text, {
|
||||
width: this.config.typography.maxWidth,
|
||||
fontSize: options.fontSize || this.config.typography.fontSize,
|
||||
fontFamily: options.fontFamily || this.config.typography.fontFamily,
|
||||
lineHeight: options.lineHeight || this.config.typography.lineHeight
|
||||
});
|
||||
|
||||
if (!layout) {
|
||||
console.error("UIDisplayHandler: Failed to calculate paragraph layout");
|
||||
this.pendingParagraphs.shift(); // Remove this paragraph
|
||||
resolve(null);
|
||||
|
||||
// Process next paragraph if any
|
||||
if (this.pendingParagraphs.length > 0) {
|
||||
this.processNextParagraph();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the original text in the layout for TTS
|
||||
layout.originalText = text;
|
||||
|
||||
// Use the layout renderer to create the DOM elements
|
||||
const paragraphElement = this.layoutRenderer.renderParagraph(layout, {
|
||||
container: this.paragraphContainer,
|
||||
id: id,
|
||||
className: options.className || '',
|
||||
style: options.style || {},
|
||||
animateWords: this.config.animation.useTypingAnimation,
|
||||
animationSpeed: this.config.animation.speed,
|
||||
tts: options.speak !== false, // Enable TTS by default
|
||||
onComplete: () => {
|
||||
// Dispatch event when paragraph is complete
|
||||
this.dispatchEvent('ui:paragraph:complete', { id });
|
||||
|
||||
// Remove this paragraph from the queue
|
||||
this.pendingParagraphs.shift();
|
||||
|
||||
// Resolve the promise with the paragraph element
|
||||
resolve(paragraphElement);
|
||||
|
||||
// Process next paragraph if any
|
||||
if (this.pendingParagraphs.length > 0) {
|
||||
this.processNextParagraph();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Scroll to the new paragraph
|
||||
if (paragraphElement) {
|
||||
paragraphElement.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("UIDisplayHandler: Error processing paragraph:", error);
|
||||
|
||||
// Remove this paragraph from the queue
|
||||
this.pendingParagraphs.shift();
|
||||
resolve(null);
|
||||
|
||||
// Process next paragraph if any
|
||||
if (this.pendingParagraphs.length > 0) {
|
||||
this.processNextParagraph();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show choices in the UI
|
||||
* @param {Array<Object>} choices - Array of choice objects
|
||||
|
||||
Reference in New Issue
Block a user