summaryrefslogtreecommitdiff
path: root/resources
diff options
context:
space:
mode:
Diffstat (limited to 'resources')
-rw-r--r--resources/js/classes/Area.js2
-rw-r--r--resources/js/classes/Item.js4
-rw-r--r--resources/js/classes/Monster.js2
-rw-r--r--resources/js/classes/Npc.js2
-rw-r--r--resources/js/classes/StatusEffect.js2
-rw-r--r--resources/js/classes/Technique.js4
-rw-r--r--resources/js/db.js1
-rw-r--r--resources/js/game.js48
-rw-r--r--resources/js/helpers.js15
-rw-r--r--resources/js/memory.js2
-rw-r--r--resources/js/story.js26
-rw-r--r--resources/js/ui.js44
12 files changed, 82 insertions, 70 deletions
diff --git a/resources/js/classes/Area.js b/resources/js/classes/Area.js
index bafa949..1b07e35 100644
--- a/resources/js/classes/Area.js
+++ b/resources/js/classes/Area.js
@@ -9,7 +9,7 @@ class Area {
}
get name () {
- return translate(this.alternateSlug) || slugToName(this.slug);
+ return translate(this.alternateSlug);
}
get isCompleted () {
diff --git a/resources/js/classes/Item.js b/resources/js/classes/Item.js
index 40089f2..c70c28a 100644
--- a/resources/js/classes/Item.js
+++ b/resources/js/classes/Item.js
@@ -4,11 +4,11 @@ class Item {
}
get name () {
- return translate(this.slug) || slugToName(this.slug);
+ return translate(this.slug);
}
get description () {
- return translate(`${this.slug}_description`) || 'ITEM_DESCRIPTION_MISSING';
+ return translate(`${this.slug}_description`);
}
get category () {
diff --git a/resources/js/classes/Monster.js b/resources/js/classes/Monster.js
index c058a75..2d34d8e 100644
--- a/resources/js/classes/Monster.js
+++ b/resources/js/classes/Monster.js
@@ -124,7 +124,7 @@ class Monster {
}
get name () {
- return translate(this.slug) || slugToName(this.slug);
+ return translate(this.slug);
}
/**
diff --git a/resources/js/classes/Npc.js b/resources/js/classes/Npc.js
index 6121bce..82dba7e 100644
--- a/resources/js/classes/Npc.js
+++ b/resources/js/classes/Npc.js
@@ -5,7 +5,7 @@ class Npc {
constructor (slug) {
this.slug = slug;
- this.name = translate(slug) || slugToName(slug.replace('spyder_', ''));
+ this.name = translate(slug);
this.spriteName = DB.npcs[slug]?.template[0].sprite_name;
}
diff --git a/resources/js/classes/StatusEffect.js b/resources/js/classes/StatusEffect.js
index d161761..1a164a1 100644
--- a/resources/js/classes/StatusEffect.js
+++ b/resources/js/classes/StatusEffect.js
@@ -44,7 +44,7 @@ class StatusEffect {
}
get name () {
- return slugToName(this.slug);
+ return translate(`status_${this.slug}`);
}
get stats () {
diff --git a/resources/js/classes/Technique.js b/resources/js/classes/Technique.js
index 5f01e64..0fa31c9 100644
--- a/resources/js/classes/Technique.js
+++ b/resources/js/classes/Technique.js
@@ -14,11 +14,11 @@ class Technique {
}
get name () {
- return translate(this.slug) || slugToName(this.slug);
+ return translate(this.slug);
}
get description () {
- return translate(`${this.slug}_description`) || 'TECHNIQUE_DESCRIPTION_MISSING';
+ return translate(`${this.slug}_description`);
}
get types () {
diff --git a/resources/js/db.js b/resources/js/db.js
index 6e53b7e..d564851 100644
--- a/resources/js/db.js
+++ b/resources/js/db.js
@@ -123,6 +123,7 @@ async function initializeDB () {
DB.elements[element] = await fetchDBData(`/modules/tuxemon/mods/tuxemon/db/element/${element}.json`).then((response) => response.json());
}
+ await fetchTranslation('en_US'); // fallback
await fetchTranslation(Memory.state.Settings.language);
applyTranslation();
diff --git a/resources/js/game.js b/resources/js/game.js
index 5abc42f..6c3a393 100644
--- a/resources/js/game.js
+++ b/resources/js/game.js
@@ -98,7 +98,7 @@ const Game = {
const money = calculateAwardedMoney(Memory.state.opponent.activeMonster);
Memory.state.money += money;
Game.addPhaseEvent('postTurn', () => {
- Game.log(translate('game:battle:money:get', true).replace('{amount}', money));
+ Game.log(translate('game:battle:money:get').replace('{amount}', money));
});
// exp
@@ -171,9 +171,9 @@ const Game = {
Memory.state.money -= totalHealingCenterPrice;
Game.addPhaseEvent('postTurnEnd', () => {
- Game.log(translate('game:battle:defeat', true));
+ Game.log(translate('game:battle:defeat'));
Game.log(
- translate('game:battle:defeat:recovery_price', true)
+ translate('game:battle:defeat:recovery_price')
.replace('{amount}', formatPrice(totalHealingCenterPrice))
.replace('{name}', Memory.state.currentArea.name)
);
@@ -251,7 +251,7 @@ const Game = {
};
log(
- translate('game:battle:technique:attempt', true)
+ translate('game:battle:technique:attempt')
.replace('{monster.name}', user.name)
.replace('{technique.name}', technique.name)
);
@@ -264,7 +264,7 @@ const Game = {
UI.drawActionFeedback(feedbackNode);
}
- log(translate('game:battle:technique:attempt:fail:recharge', true), 1);
+ log(translate('game:battle:technique:attempt:fail:recharge'), 1);
canUse = false;
}
@@ -276,7 +276,7 @@ const Game = {
UI.drawActionFeedback(feedbackNode);
}
- log(translate('game:battle:technique:attempt:fail:noddingoff', true), 1);
+ log(translate('game:battle:technique:attempt:fail:noddingoff'), 1);
canUse = false;
}
@@ -290,7 +290,7 @@ const Game = {
technique.use();
Game.doBattleAnimation && UI.drawDamageMiss(UI.createDamageMiss());
- log(translate('game:battle:technique:attempt:fail:miss', true), 1);
+ log(translate('game:battle:technique:attempt:fail:miss'), 1);
return;
}
@@ -309,7 +309,7 @@ const Game = {
Game.addBattlePhaseEvent('action', user, () => {
Game.log(
- translate('game:battle:technique:use', true)
+ translate('game:battle:technique:use')
.replace('{monster.name}', user.name)
.replace('{technique.name}', technique.name)
);
@@ -336,7 +336,7 @@ const Game = {
}
Game.log(
- translate('game:battle:technique:use:damage', true)
+ translate('game:battle:technique:use:damage')
.replace('{amount}', damage)
.replace('{name}', target.name),
1
@@ -367,7 +367,7 @@ const Game = {
recipient.hp += heal;
Game.log(
- translate('game:battle:technique:use:healing', true)
+ translate('game:battle:technique:use:healing')
.replace('{amount}', heal),
1
);
@@ -406,9 +406,9 @@ const Game = {
recipient.statusEffect = statusEffect;
Game.log(
- translate('game:battle:technique:use:status', true)
+ translate('game:battle:technique:use:status')
.replace('{monster.name}', recipient.name)
- .replace('{status_effect.name}', translate(`status_${statusEffect.slug}`, true)),
+ .replace('{status_effect.name}', translate(`status_${statusEffect.slug}`)),
1
);
}
@@ -435,9 +435,9 @@ const Game = {
// if still 0 turns left after remove action
if (monster.statusEffect.turnsLeft === 0) {
Game.log(
- translate('game:battle:status_effect:removed', true)
+ translate('game:battle:status_effect:removed')
.replace('{monster.name}', monster.name)
- .replace('{status_effect.name}', translate(`status_${monster.statusEffect.slug}`, true))
+ .replace('{status_effect.name}', translate(`status_${monster.statusEffect.slug}`))
);
monster.statusEffect = null;
@@ -451,9 +451,9 @@ const Game = {
const logStatusIs = () => {
Game.log(
- translate('game:battle:status_effect:is', true)
+ translate('game:battle:status_effect:is')
.replace('{monster.name}', monster.name)
- .replace('{status_effect.name}', translate(`status_${monster.statusEffect.slug}`, true))
+ .replace('{status_effect.name}', translate(`status_${monster.statusEffect.slug}`))
);
}
@@ -963,7 +963,7 @@ const Game = {
const activeBall = Game.getItemFromInventory(Memory.state.player.inventory, Memory.state.activeBall);
// remove ball
- Game.log(translate('game:catch:ball:throw', true).replace('{ball}', activeBall.name));
+ Game.log(translate('game:catch:ball:throw').replace('{ball}', activeBall.name));
activeBall.quantity--;
if (activeBall.quantity === 0) {
Game.removeItemFromInventory(Memory.state.player.inventory, Memory.state.activeBall);
@@ -972,7 +972,7 @@ const Game = {
}
// attempt capture
- Game.log(translate('game:catch:attempt', true), 1);
+ Game.log(translate('game:catch:attempt'), 1);
let success = true;
let attempts = 1;
const maxAttempts = 4;
@@ -980,8 +980,8 @@ const Game = {
success = checkCapture(playerMonster, opposingMonster, activeBall);
if (!success) {
- Game.log(translate('game:catch:attempt:nr:success', true).replace('{nr}', attempts), 2);
- Game.log(translate('game:catch:broke_free', true).replace('{monster}', opposingMonster.name), 1);
+ Game.log(translate('game:catch:attempt:nr:success').replace('{nr}', attempts), 2);
+ Game.log(translate('game:catch:broke_free').replace('{monster}', opposingMonster.name), 1);
Memory.state.Game.isInBattle = true;
UI.drawStatus();
@@ -990,7 +990,7 @@ const Game = {
return; // can't catch
}
- Game.log(translate('game:catch:attempt:nr:fail', true).replace('{nr}', attempts), 2);
+ Game.log(translate('game:catch:attempt:nr:fail').replace('{nr}', attempts), 2);
attempts++;
}
@@ -1002,16 +1002,16 @@ const Game = {
caughtMonster.level = Memory.state.opponent.activeMonster.level;
caughtMonster.hp = Memory.state.opponent.activeMonster.hp;
- Game.log(translate('game:catch:caught', true).replace('{monster}', caughtMonster.name), 1);
+ Game.log(translate('game:catch:caught').replace('{monster}', caughtMonster.name), 1);
if (Memory.state.player.monsters.length < 6) {
Memory.state.player.monsters.push(caughtMonster);
- Game.log(translate('game:catch:to_party', true).replace('{monster}', caughtMonster.name), 2);
+ Game.log(translate('game:catch:to_party').replace('{monster}', caughtMonster.name), 2);
} else {
Memory.state.monsters.push(caughtMonster);
- Game.log(translate('game:catch:to_box', true).replace('{monster}', caughtMonster.name), 2);
+ Game.log(translate('game:catch:to_box').replace('{monster}', caughtMonster.name), 2);
}
await Game.encounterWildMonster();
diff --git a/resources/js/helpers.js b/resources/js/helpers.js
index aa149b1..cee9166 100644
--- a/resources/js/helpers.js
+++ b/resources/js/helpers.js
@@ -68,14 +68,19 @@ function randomString () {
/**
* @param {string} msgid
+ * @param {boolean} useFallback
*
* @returns {string}
*/
-function translate (msgid, showTranslationMissing = false) {
+function translate (msgid, useFallback = true) {
let translation = DB.translations[Memory.state.Settings.language][msgid];
- if (!translation && showTranslationMissing) {
- translation = (translate('translation_missing') || 'translation_missing') + `: ${msgid}`;
+ if (!translation && useFallback) {
+ translation = DB.translations['en_US'][msgid];
+
+ if (!translation) {
+ translation = (translate('translation_missing', false) || 'translation_missing') + `: ${msgid}`;
+ }
}
return translation;
@@ -89,7 +94,7 @@ function applyTranslation () {
}
parentNode.querySelectorAll('[data-i18n-msgid]').forEach((node) => {
- node.innerHTML = translate(node.dataset.i18nMsgid, true);
+ node.innerHTML = translate(node.dataset.i18nMsgid);
});
parentNode.querySelectorAll('[data-i18n-properties]').forEach((node) => {
@@ -99,7 +104,7 @@ function applyTranslation () {
const property = properties[idx];
const msgid = msgids[idx];
- node.setAttribute(property, translate(msgid, true))
+ node.setAttribute(property, translate(msgid))
}
});
});
diff --git a/resources/js/memory.js b/resources/js/memory.js
index c0fa171..421cecb 100644
--- a/resources/js/memory.js
+++ b/resources/js/memory.js
@@ -76,7 +76,7 @@ const Memory = {
saveToLocalStorage () {
const lastWrite = new Date(localStorage.getItem('lastWrite'));
if (Math.abs(new Date() - lastWrite) / (1000 * 60 * 60 * 24) >= 0.25) {
- localStorage.setItem(`state_${(new Date()).toLocaleDateString()}_${(new Date()).getTime()}`, localStorage.getItem('state'));
+ localStorage.setItem(`state_${(new Date()).toLocaleDateString()}_${(new Date()).toLocaleTimeString()}`, localStorage.getItem('state'));
}
localStorage.setItem('state', Memory.saveToString());
diff --git a/resources/js/story.js b/resources/js/story.js
index 0ceb224..d5e6486 100644
--- a/resources/js/story.js
+++ b/resources/js/story.js
@@ -20,9 +20,9 @@ const Story = {
const npcCeo = await fetchNpc(characterCeo.slug);
const npcShopKeeper = await fetchNpc(characterShopKeeper.slug);
- await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[0], true) });
- await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[1], true) });
- await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[0], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[0]) });
+ await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[1]) });
+ await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[0]) });
const possibleStarterMonsters = await Promise.all(
story.monsters.map(async (monsterData) => {
@@ -32,7 +32,7 @@ const Story = {
})
);
- const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:introduction:monster_selection:title', true) });
+ const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:introduction:monster_selection:title') });
await new Promise((resolve) => {
monsterSelection.addEventListener('starter:monster:selected', UI.wrapCallback(async (event) => {
if (!confirm(`Select ${event.detail.monster.name}?`)) {
@@ -41,7 +41,7 @@ const Story = {
event.detail.popup.remove();
- await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[1], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[1]) });
// set rival monster
Memory.state.rivalMonster = event.detail.monster.slug;
@@ -62,9 +62,9 @@ const Story = {
const characterDante = story.characters.dante;
const npcDante = await fetchNpc(characterDante.slug);
- await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[0], true) });
- await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[1], true) });
- await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[2], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[0]) });
+ await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[1]) });
+ await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[2]) });
const possibleStarterMonsters = await Promise.all(
story.monsters.map(async (monsterData) => {
@@ -74,7 +74,7 @@ const Story = {
})
);
- const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:select_starter_monster:monster_selection:title', true) });
+ const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:select_starter_monster:monster_selection:title') });
await new Promise((resolve) => {
monsterSelection.addEventListener('starter:monster:selected', UI.wrapCallback(async (event) => {
if (!confirm(`Select ${event.detail.monster.name}?`)) {
@@ -117,17 +117,17 @@ const Story = {
});
await Memory.state.opponent.initialize();
- await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[0], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[0]) });
await Story.battle();
if (Game.didWinStoryBattle) {
- await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[1], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[1]) });
} else {
- await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[2], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[2]) });
}
- await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[3], true) });
+ await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[3]) });
Game.healParty();
},
diff --git a/resources/js/ui.js b/resources/js/ui.js
index 3aa0c98..04186f5 100644
--- a/resources/js/ui.js
+++ b/resources/js/ui.js
@@ -283,7 +283,7 @@ const UI = {
createElementTypeIcon (type) {
const img = document.createElement('img');
img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/element/${type}_type.png`;
- img.title = translate(type) || slugToName(type);
+ img.title = translate(type);
return img;
},
@@ -301,14 +301,14 @@ const UI = {
if (statusEffect.slug === 'faint') {
const node = document.createElement('b');
node.innerHTML = 'X';
- node.title = translate(`status_${statusEffect.slug}`) || statusEffect.name;
+ node.title = translate(`status_${statusEffect.slug}`);
return node;
}
const img = document.createElement('img');
img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/status/icon_${statusEffect.slug}.png`;
- img.title = translate(`status_${statusEffect.slug}`) || statusEffect.name;
+ img.title = translate(`status_${statusEffect.slug}`);
return img;
},
@@ -389,7 +389,7 @@ const UI = {
techniqueNode.querySelector('[data-template-slot="name"]').textContent = technique.name;
techniqueNode.querySelector('[data-template-slot="recharge"]').textContent = technique.rechargeLength;
techniqueNode.querySelector('[data-template-slot="types"]').innerHTML = technique.types.map((type) => UI.createElementTypeIcon(type).outerHTML).join('');
- techniqueNode.querySelector('[data-template-slot="range"]').textContent = translate(technique.range) || slugToName(technique.range);
+ techniqueNode.querySelector('[data-template-slot="range"]').textContent = translate(technique.range);
techniqueNode.querySelector('[data-template-slot="power"]').textContent = technique.power;
techniqueNode.querySelector('[data-template-slot="accuracy"]').textContent = technique.accuracy;
@@ -792,7 +792,7 @@ const UI = {
});
if (applicableMonsters.length === 0) {
- alert(translate('ui:no_applicable_monsters', true));
+ alert(translate('ui:no_applicable_monsters'));
return;
}
@@ -823,11 +823,11 @@ const UI = {
template.querySelector('[data-template-slot="box.withdraw"]').addEventListener('click', UI.wrapCallback(() => {
if (Memory.state.monsters.length === 0) {
- alert(translate('ui:healing_center:box:withdraw:no_tuxemon_in_box', true));
+ alert(translate('ui:healing_center:box:withdraw:no_tuxemon_in_box'));
return;
}
if (Memory.state.player.monsters.length === 6) {
- alert(translate('ui:healing_center:box:withdraw:no_space_in_party', true));
+ alert(translate('ui:healing_center:box:withdraw:no_space_in_party'));
return;
}
@@ -849,7 +849,7 @@ const UI = {
template.querySelector('[data-template-slot="box.deposit"]').addEventListener('click', UI.wrapCallback(() => {
if (Memory.state.player.monsters.length === 1) {
- alert(translate('ui:healing_center:box:deposit:last_tuxemon', true));
+ alert(translate('ui:healing_center:box:deposit:last_tuxemon'));
return;
}
@@ -871,7 +871,7 @@ const UI = {
template.querySelector('[data-template-slot="box.view"]').addEventListener('click', UI.wrapCallback(() => {
if (Memory.state.monsters.length === 0) {
- alert(translate('ui:healing_center:box:view:no_tuxemon_in_box', true));
+ alert(translate('ui:healing_center:box:view:no_tuxemon_in_box'));
return;
}
@@ -1175,8 +1175,7 @@ const UI = {
const connection = currentArea.connections[connectionSlug];
const connectionNode = UI.createTemplate(Template.areaSelectionItem);
- connectionNode.querySelector('[data-template-slot="text"]').textContent =
- translate(connection['modules/tuxemon.slug']) || slugToName(connection['modules/tuxemon.slug']);
+ connectionNode.querySelector('[data-template-slot="text"]').textContent = translate(connection['modules/tuxemon.slug']);
let canGo = true;
for (const condition of connection.conditions) {
@@ -1455,11 +1454,11 @@ const UI = {
template.querySelector('[data-template-slot="exp"]').innerHTML = `${monster.exp} / ${monster.getExperienceRequired(1)}`;
- template.querySelector('[data-template-slot="stats.melee.name"]').textContent = translate(StatType.melee) || slugToName(StatType.melee);
- template.querySelector('[data-template-slot="stats.armour.name"]').textContent = translate(StatType.armour) || slugToName(StatType.armour);
- template.querySelector('[data-template-slot="stats.ranged.name"]').textContent = translate(StatType.ranged) || slugToName(StatType.ranged);
- template.querySelector('[data-template-slot="stats.dodge.name"]').textContent = translate(StatType.dodge) || slugToName(StatType.dodge);
- template.querySelector('[data-template-slot="stats.speed.name"]').textContent = translate(StatType.speed) || slugToName(StatType.speed);
+ template.querySelector('[data-template-slot="stats.melee.name"]').textContent = translate(StatType.melee);
+ template.querySelector('[data-template-slot="stats.armour.name"]').textContent = translate(StatType.armour);
+ template.querySelector('[data-template-slot="stats.ranged.name"]').textContent = translate(StatType.ranged);
+ template.querySelector('[data-template-slot="stats.dodge.name"]').textContent = translate(StatType.dodge);
+ template.querySelector('[data-template-slot="stats.speed.name"]').textContent = translate(StatType.speed);
template.querySelector('[data-template-slot="stats.melee.value"]').textContent = monster.stats.melee;
template.querySelector('[data-template-slot="stats.armour.value"]').textContent = monster.stats.armour;
@@ -1671,7 +1670,7 @@ const UI = {
template.classList.add('inventory__monster-selection');
if (template.children.length === 0) {
- alert(translate('ui:no_applicable_monsters', true));
+ alert(translate('ui:no_applicable_monsters'));
return;
}
@@ -1917,7 +1916,7 @@ const UI = {
// Clear save data
template.querySelector('[data-template-slot="clearLocalSaveData"]').addEventListener('click', UI.wrapCallback(() => {
- if (confirm(translate('ui:settings:clear_local_save_data:confirm', true))) {
+ if (confirm(translate('ui:settings:clear_local_save_data:confirm'))) {
localStorage.removeItem('state');
window.location.reload();
}
@@ -1940,6 +1939,9 @@ const UI = {
/**
* @param {HTMLElement} popup
+ * @param {Object} data
+ * @param {Npc} data.speaker
+ * @param {string} data.text
*
* @returns {HTMLElement}
*/
@@ -1961,7 +1963,7 @@ const UI = {
/**
* @param {HTMLElement} popup
*
- * @returns {Promise<any>}
+ * @returns {Promise<void>}
*/
drawStoryPopup (popup) {
UI.drawPopup(popup);
@@ -1979,6 +1981,10 @@ const UI = {
},
/**
+ * @param {Object} data
+ * @param {Npc} data.speaker
+ * @param {string} data.text
+ *
* @returns {Promise<any>}
*/
async buildAndShowStoryPopup ({ speaker, text }) {