61 lines
1.4 KiB
Plaintext
61 lines
1.4 KiB
Plaintext
import { cancel, later } from "@ember/runloop";
|
|
import { htmlSafe } from "@ember/template";
|
|
import Modifier from "ember-modifier";
|
|
import { cook } from "discourse/lib/text";
|
|
|
|
const STREAMED_TEXT_SPEED = 15;
|
|
|
|
export default class SmoothStreamTextModifier extends Modifier {
|
|
typingTimer = null;
|
|
displayedText = "";
|
|
|
|
modify(element, [text, haltAnimation]) {
|
|
if (haltAnimation) {
|
|
return;
|
|
}
|
|
this._startTypingAnimation(element, text);
|
|
}
|
|
|
|
async _startTypingAnimation(element, text) {
|
|
if (this.typingTimer) {
|
|
cancel(this.typingTimer);
|
|
}
|
|
|
|
if (this.displayedText.length === 0) {
|
|
element.innerHTML = "";
|
|
}
|
|
|
|
this._typeCharacter(element, text);
|
|
}
|
|
|
|
async _typeCharacter(element, text) {
|
|
if (this.displayedText.length < text.length) {
|
|
this.displayedText += text.charAt(this.displayedText.length);
|
|
|
|
try {
|
|
const cookedText = await cook(this.displayedText);
|
|
element.classList.add("cooked");
|
|
element.innerHTML = htmlSafe(cookedText);
|
|
} catch (error) {
|
|
console.error("Error cooking text during typing: ", error);
|
|
}
|
|
|
|
this.typingTimer = later(
|
|
this,
|
|
this._typeCharacter,
|
|
element,
|
|
text,
|
|
STREAMED_TEXT_SPEED
|
|
);
|
|
} else {
|
|
this.typingTimer = null;
|
|
}
|
|
}
|
|
|
|
willRemove() {
|
|
if (this.typingTimer) {
|
|
cancel(this.typingTimer);
|
|
}
|
|
}
|
|
}
|