MCPcopy Create free account
hub / github.com/Monogatari/Monogatari / displayNvlDialog

Method displayNvlDialog

src/actions/Dialog.ts:288–359  ·  view source on GitHub ↗
(dialog: string, clearDialog: string, character: string, animation: boolean)

Source from the content-addressed store, hash-verified

286 }
287
288 displayNvlDialog(dialog: string, clearDialog: string, character: string, animation: boolean): void {
289 const textBox = this.engine.element().find('[data-component="text-box"]').get(0) as any;
290
291 if (!textBox) {
292 this.engine.debug.error('Text box component not found');
293 return;
294 }
295
296 if (textBox.props?.mode !== 'nvl') {
297 Dialog.reset();
298 // NOTE: setProps does NOT trigger a re-render — it only updates the
299 // mode attribute so CSS (text-box[mode="nvl"]) applies. The ADV-mode
300 // type-writer element persists and serves as the container for NVL
301 // dialog entries appended to [data-ui="say"].
302 textBox.setProps({ mode: 'nvl' });
303
304 // We need to re-apply any custom classes here because the reset clears them
305 this._handleCustomClasses(textBox);
306 }
307
308 // Remove contents from the dialog area.
309 const previous = this.engine.element().find('[data-component="text-box"]').data('speaking');
310 this.engine.element().find('[data-component="text-box"]').data('speaking', character);
311
312 // Determine if we should animate (respects NVLTypeAnimation setting)
313 const shouldAnimate = animation && this.engine.setting('NVLTypeAnimation') === true;
314
315 // Build the dialog entry HTML
316 if (character !== '_narrator') {
317 const charData = this.engine.character(character);
318 if (previous !== character) {
319 this.engine.element().find('[data-ui="say"] [data-spoke]').last().addClass('nvl-dialog-footer');
320 this.engine.element().find('[data-ui="say"]').append(`<div data-spoke="${character}" class='named'><span style='color:${charData?.color ?? ''};'>${this.engine.replaceVariables(charData?.name ?? '')}: </span><type-writer></type-writer></div>`);
321 } else {
322 this.engine.element().find('[data-ui="say"]').append(`<div data-spoke="${character}"><type-writer></type-writer></div>`);
323 }
324 } else {
325 if (previous !== character) {
326 this.engine.element().find('[data-ui="say"] [data-spoke]').last().addClass('nvl-dialog-footer');
327 }
328 this.engine.element().find('[data-ui="say"]').append(`<div data-spoke="${character}" class='unnamed'><type-writer></type-writer></div>`);
329 }
330
331 // Wait for the new type-writer component to be fully mounted before
332 // setting its content. Using ready() is more reliable than
333 // requestAnimationFrame since Pandora's connectedCallback is async.
334 const elements = $_('[data-ui="say"] [data-spoke] type-writer');
335 const last = elements.last().get(0) as TypeWriter | undefined;
336
337 if (last && typeof (last as any).ready === 'function') {
338 (last as any).ready(() => {
339 last.setContent(dialog, shouldAnimate);
340 });
341 } else if (last) {
342 last.setContent(dialog, shouldAnimate);
343 }
344
345 const text_box = this.engine.element().find('[data-component="text-box"]');

Callers 1

displayDialogMethod · 0.95

Calls 9

_handleCustomClassesMethod · 0.95
settingMethod · 0.80
characterMethod · 0.80
replaceVariablesMethod · 0.80
setContentMethod · 0.80
checkUnreadMethod · 0.80
getMethod · 0.65
elementMethod · 0.45
resetMethod · 0.45

Tested by

no test coverage detected