Skip to content

Commit fb6e674

Browse files
author
web3blind
committed
Fix mobile install and home status scales
1 parent 9545562 commit fb6e674

9 files changed

Lines changed: 142 additions & 32 deletions

File tree

app/index.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@
114114
<script src="js/config.js?v=20260621m"></script>
115115

116116
<!-- I18n -->
117-
<script src="js/i18n/ru.js?v=20260711a"></script>
118-
<script src="js/i18n/en.js?v=20260711a"></script>
117+
<script src="js/i18n/ru.js?v=20260711d"></script>
118+
<script src="js/i18n/en.js?v=20260711d"></script>
119119

120120
<!-- Utilities -->
121121
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -170,17 +170,17 @@
170170

171171
<!-- UI Components -->
172172
<script src="js/ui/sound.js?v=20260711c"></script>
173-
<script src="js/ui/components/progress-bar.js"></script>
173+
<script src="js/ui/components/progress-bar.js?v=20260711d"></script>
174174
<script src="js/ui/components/toast.js?v=20260711b"></script>
175175
<script src="js/ui/components/modal.js"></script>
176176
<script src="js/ui/components/nav.js"></script>
177-
<script src="js/ui/components/battle-narrator.js"></script>
177+
<script src="js/ui/components/battle-narrator.js?v=20260711d"></script>
178178

179179
<!-- UI Screens -->
180180
<script src="js/ui/screens/landing.js"></script>
181181
<script src="js/ui/screens/login.js?v=20260711a"></script>
182182
<script src="js/ui/screens/onboarding.js"></script>
183-
<script src="js/ui/screens/home.js?v=20260711a"></script>
183+
<script src="js/ui/screens/home.js?v=20260711d"></script>
184184
<script src="js/ui/screens/character.js?v=20260621l"></script>
185185
<script src="js/ui/screens/hunt.js"></script>
186186
<script src="js/ui/screens/inventory.js?v=20260621l"></script>
@@ -193,11 +193,11 @@
193193
<script src="js/ui/screens/crafting.js?v=20260621j"></script>
194194
<script src="js/ui/screens/quests.js?v=20260621n"></script>
195195
<script src="js/ui/screens/world-boss.js"></script>
196-
<script src="js/ui/screens/settings.js?v=20260711c"></script>
197-
<script src="js/ui/screens/help.js"></script>
196+
<script src="js/ui/screens/settings.js?v=20260711d"></script>
197+
<script src="js/ui/screens/help.js?v=20260711d"></script>
198198
<script src="js/ui/screens/leaderboard.js"></script>
199199

200200
<!-- Main App Controller (must be last) -->
201-
<script src="js/ui/app.js?v=20260711a"></script>
201+
<script src="js/ui/app.js?v=20260711d"></script>
202202
</body>
203203
</html>

app/js/i18n/en.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ var LangEN = {
122122
home_install_shortcut: 'Game shortcut on your phone',
123123
home_install_shortcut_text: 'Add Viz Magic to your phone home screen so you do not have to find a saved link after the game window closes. This is a normal PWA shortcut install, no app store needed.',
124124
home_install_shortcut_button: 'Install or show instructions',
125-
home_install_shortcut_manual: 'If the install prompt does not appear: open the browser or Telegram menu and choose Add to Home screen / Install app.',
125+
home_install_shortcut_manual: 'If the install prompt does not appear, add the shortcut manually:',
126+
home_install_step_1: 'Open the browser menu or Telegram three-dot menu.',
127+
home_install_step_2: 'Choose Add to Home screen, Install app, or a similar item.',
128+
home_install_step_3: 'Confirm the Viz Magic shortcut.',
129+
home_install_shortcut_installed: 'Viz Magic shortcut installed.',
130+
home_install_shortcut_already: 'The game is already running as an installed app.',
126131

127132
// Character
128133
char_title: 'Character',
@@ -340,6 +345,8 @@ var LangEN = {
340345
// Battle Narrator
341346
narrator_label: 'Battle Narrator',
342347
narrator_toggle: 'Battle Narrator',
348+
narrator_test: 'Test narrator',
349+
narrator_test_message: 'Battle Narrator is online. If your screen reader is enabled, it should read this message.',
343350
narrator_pve_attack: 'You used {spell}. {creature} takes {damage} damage.',
344351
narrator_critical: 'Critical hit!',
345352
narrator_hunt_victory: 'Victory! {creature} defeated. {xp} XP gained.',

app/js/i18n/ru.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ var LangRU = {
122122
home_install_shortcut: 'Ярлык игры на телефоне',
123123
home_install_shortcut_text: 'Чтобы не искать сохранённую ссылку после закрытия окна, добавьте Viz Magic на главный экран телефона. Это обычная установка PWA-ярлыка без магазина приложений.',
124124
home_install_shortcut_button: 'Установить или показать инструкцию',
125-
home_install_shortcut_manual: 'Если кнопка установки не появилась: откройте меню браузера или Telegram, выберите «Добавить на главный экран» / «Установить приложение».',
125+
home_install_shortcut_manual: 'Если системное окно установки не появилось, установите ярлык вручную:',
126+
home_install_step_1: 'Откройте меню браузера или меню Telegram с тремя точками.',
127+
home_install_step_2: 'Выберите «Добавить на главный экран», «Установить приложение» или похожий пункт.',
128+
home_install_step_3: 'Подтвердите добавление ярлыка Viz Magic.',
129+
home_install_shortcut_installed: 'Ярлык Viz Magic установлен.',
130+
home_install_shortcut_already: 'Игра уже открыта как установленное приложение.',
126131

127132
// Character
128133
char_title: 'Персонаж',
@@ -340,6 +345,8 @@ var LangRU = {
340345
// Battle Narrator
341346
narrator_label: 'Боевой Рассказчик',
342347
narrator_toggle: 'Боевой Рассказчик',
348+
narrator_test: 'Проверить рассказчика',
349+
narrator_test_message: 'Боевой рассказчик на связи. Если включён экранный диктор, он должен прочитать это сообщение.',
343350
narrator_pve_attack: 'Ты использовал {spell}. {creature} получает {damage} урона.',
344351
narrator_critical: 'Критический удар!',
345352
narrator_hunt_victory: 'Победа! {creature} повержен. Получено {xp} опыта.',
@@ -538,9 +545,9 @@ var LangRU = {
538545

539546
// Navigation (marketplace/crafting)
540547
nav_bazaar: 'Базар',
541-
nav_craft: 'Ковка',
548+
nav_craft: 'Мастерская',
542549
nav_marketplace: 'Базар',
543-
nav_crafting: 'Ковка',
550+
nav_crafting: 'Мастерская',
544551

545552
// Marketplace
546553
market_title: 'Базар',
@@ -789,7 +796,7 @@ var LangRU = {
789796
quest_abandoned: 'Задание отменено.',
790797
chronicle_unknown_guild: 'неизвестная гильдия',
791798
quest_type_hunt: 'Охота',
792-
quest_type_craft: 'Ковка',
799+
quest_type_craft: 'Мастерская',
793800
quest_type_duel: 'Дуэль',
794801
quest_type_explore: 'Исследование',
795802
quest_type_social: 'Общение',
@@ -837,7 +844,7 @@ var LangRU = {
837844
quest_daily_bless: 'Ежедневные Благословения',
838845
quest_daily_bless_desc: 'Благословите других магов сегодня.',
839846
quest_daily_help_text: 'Ежедневное пророчество нужно принять, а потом выполнить его цель. Для благословений — откройте Хронику и благословляйте других магов.',
840-
quest_daily_craft: 'Ежедневная Ковка',
847+
quest_daily_craft: 'Ежедневная Мастерская',
841848
quest_daily_craft_desc: 'Создайте предмет сегодня.',
842849
quest_daily_duel: 'Ежедневная Дуэль',
843850
quest_daily_duel_desc: 'Выиграйте дуэль сегодня.',
@@ -923,8 +930,8 @@ var LangRU = {
923930
help_section_armageddon: 'Армагеддон',
924931
help_armageddon_text: 'Потратьте 100% маны ради 100× опыта от обычного удара. Требует артефакт Камень Армагеддона. Дроп: Thornvine (Lv5+, шанс 0.5%). Крафт: Echo Shards ×3 + Shadow Shard ×3 + Fire Dust ×5 на 10 уровне (стоит 5% маны). Подтвердите чекбокс перед запуском — мана восстанавливается ~5 дней.',
925932

926-
help_section_crafting: 'Крафт',
927-
help_crafting_text: 'Откройте экран Крафт, выберите рецепт и нажмите «Создать». Материалы расходуются. Качество зависит от INT и хеша блока.',
933+
help_section_crafting: 'Мастерская',
934+
help_crafting_text: 'Откройте Мастерскую, выберите рецепт и нажмите «Создать». Материалы расходуются. Качество зависит от INT и хеша блока.',
928935

929936
help_section_marketplace: 'Рынок',
930937
help_marketplace_text: 'Обзор → купите выставленные предметы. Продать → выставьте свои предметы за Печати Мира. Обмен → прямая передача предмета другому магу.',

app/js/ui/app.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ var App = (function() {
280280
event.preventDefault();
281281
_deferredInstallPrompt = event;
282282
});
283+
window.addEventListener('appinstalled', function() {
284+
_deferredInstallPrompt = null;
285+
if (typeof Toast !== 'undefined') {
286+
Toast.success(Helpers.t('home_install_shortcut_installed'));
287+
}
288+
});
283289
if ('serviceWorker' in navigator) {
284290
navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function() {
285291
console.log('Service Worker Registered');
@@ -290,15 +296,40 @@ var App = (function() {
290296
}
291297

292298
function installShortcut() {
299+
if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) {
300+
if (typeof Toast !== 'undefined') Toast.info(Helpers.t('home_install_shortcut_already'), 5000, { key: 'install_shortcut_already' });
301+
return;
302+
}
293303
if (_deferredInstallPrompt) {
294304
_deferredInstallPrompt.prompt();
295-
_deferredInstallPrompt.userChoice.then(function() {
305+
_deferredInstallPrompt.userChoice.then(function(choice) {
296306
_deferredInstallPrompt = null;
307+
if (choice && choice.outcome === 'accepted' && typeof Toast !== 'undefined') {
308+
Toast.success(Helpers.t('home_install_shortcut_installed'));
309+
} else {
310+
_showInstallInstructions();
311+
}
297312
});
298313
return;
299314
}
315+
_showInstallInstructions();
316+
}
317+
318+
function _showInstallInstructions() {
319+
var text = '<p>' + Helpers.t('home_install_shortcut_manual') + '</p>' +
320+
'<ol>' +
321+
'<li>' + Helpers.t('home_install_step_1') + '</li>' +
322+
'<li>' + Helpers.t('home_install_step_2') + '</li>' +
323+
'<li>' + Helpers.t('home_install_step_3') + '</li>' +
324+
'</ol>';
325+
if (typeof Modal !== 'undefined' && Modal.show) {
326+
Modal.show(Helpers.t('home_install_shortcut'), text, [
327+
{ label: Helpers.t('close'), action: function() { Modal.close(); } }
328+
]);
329+
return;
330+
}
300331
if (typeof Toast !== 'undefined') {
301-
Toast.info(Helpers.t('home_install_shortcut_manual'), 6000, { key: 'install_shortcut_manual' });
332+
Toast.info(Helpers.t('home_install_shortcut_manual'), 9000, { key: 'install_shortcut_manual' });
302333
}
303334
}
304335

app/js/ui/components/progress-bar.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ var ProgressBar = (function() {
1212
function create(opts) {
1313
var pct = Math.min(100, Math.floor((opts.value / opts.max) * 100));
1414
var color = opts.color || 'var(--color-primary)';
15-
var text = opts.showText !== false ? (opts.value + ' / ' + opts.max) : '';
15+
var displayValue = (typeof opts.displayValue !== 'undefined') ? opts.displayValue : opts.value;
16+
var displayMax = (typeof opts.displayMax !== 'undefined') ? opts.displayMax : opts.max;
17+
var text = opts.showText !== false ? (displayValue + ' / ' + displayMax) : '';
18+
var ariaValue = (typeof opts.ariaValue !== 'undefined') ? opts.ariaValue : displayValue;
19+
var ariaMax = (typeof opts.ariaMax !== 'undefined') ? opts.ariaMax : displayMax;
1620

1721
return '<div class="progress-bar-wrapper">' +
1822
(opts.label ? '<span class="progress-label">' + Helpers.escapeHtml(opts.label) + '</span>' : '') +
1923
'<div class="progress-bar" role="progressbar" ' +
20-
'aria-valuenow="' + opts.value + '" aria-valuemin="0" aria-valuemax="' + opts.max + '" ' +
21-
'aria-label="' + Helpers.escapeHtml(opts.label || '') + ' ' + opts.value + ' of ' + opts.max + '"' +
24+
'aria-valuenow="' + ariaValue + '" aria-valuemin="0" aria-valuemax="' + ariaMax + '" ' +
25+
'aria-label="' + Helpers.escapeHtml(opts.label || '') + ' ' + ariaValue + ' of ' + ariaMax + '"' +
2226
(opts.id ? ' id="' + opts.id + '"' : '') + '>' +
2327
'<div class="progress-fill" style="width:' + pct + '%;background:' + color + '"></div>' +
2428
(text ? '<span class="progress-text">' + text + '</span>' : '') +
@@ -28,16 +32,18 @@ var ProgressBar = (function() {
2832
/**
2933
* Update an existing progress bar
3034
*/
31-
function update(id, value, max) {
35+
function update(id, value, max, displayValue, displayMax) {
3236
var el = Helpers.$(id);
3337
if (!el) return;
3438
var pct = Math.min(100, Math.floor((value / max) * 100));
35-
el.setAttribute('aria-valuenow', value);
36-
el.setAttribute('aria-valuemax', max);
39+
var shownValue = (typeof displayValue !== 'undefined') ? displayValue : value;
40+
var shownMax = (typeof displayMax !== 'undefined') ? displayMax : max;
41+
el.setAttribute('aria-valuenow', shownValue);
42+
el.setAttribute('aria-valuemax', shownMax);
3743
var fill = el.querySelector('.progress-fill');
3844
if (fill) fill.style.width = pct + '%';
3945
var text = el.querySelector('.progress-text');
40-
if (text) text.textContent = value + ' / ' + max;
46+
if (text) text.textContent = shownValue + ' / ' + shownMax;
4147
}
4248

4349
return { create: create, update: update };

app/js/ui/screens/home.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ var HomeScreen = (function() {
77

88
var PRIMARY_HOME_SCREENS = ['home', 'hunt', 'map', 'guild', 'marketplace', 'crafting', 'character', 'help', 'leaderboard'];
99
var SECONDARY_HOME_SCREENS = ['inventory', 'chronicle', 'arena', 'quests', 'world-boss', 'settings'];
10+
var HOME_HP_DISPLAY_MAX = 5000;
11+
var HOME_XP_DISPLAY_MAX = 3000;
1012

1113
function render() {
1214
var t = Helpers.t;
@@ -25,6 +27,8 @@ var HomeScreen = (function() {
2527
var xpNeeded = GameFormulas.xpForLevel(character.level + 1) || 1000;
2628
var xpCurrent = character.xp - GameFormulas.totalXpForLevel(character.level);
2729
if (xpCurrent < 0) xpCurrent = 0;
30+
var hpShown = _scaleForDisplay(character.hp, character.maxHp, HOME_HP_DISPLAY_MAX);
31+
var xpShown = _scaleForDisplay(xpCurrent, xpNeeded, HOME_XP_DISPLAY_MAX);
2832

2933
el.innerHTML =
3034
'<div class="home-dashboard">' +
@@ -38,8 +42,8 @@ var HomeScreen = (function() {
3842
'<h1>' + t('home_welcome') + ', ' + Helpers.escapeHtml(character.name) + '</h1>' +
3943
'<p>' + Helpers.classIcon(character.className) + ' ' + t('class_' + character.className) +
4044
' \u2022 ' + t('home_level') + ' ' + character.level + '</p>' +
41-
ProgressBar.create({id:'hp-bar', label:'HP', value:character.hp, max:character.maxHp, color:'#e53935'}) +
42-
ProgressBar.create({id:'xp-bar', label:'XP', value:xpCurrent, max:xpNeeded, color:'#ffc107'}) +
45+
ProgressBar.create({id:'hp-bar', label:'HP', value:character.hp, max:character.maxHp, displayValue:hpShown, displayMax:HOME_HP_DISPLAY_MAX, color:'#e53935'}) +
46+
ProgressBar.create({id:'xp-bar', label:'XP', value:xpCurrent, max:xpNeeded, displayValue:xpShown, displayMax:HOME_XP_DISPLAY_MAX, color:'#ffc107'}) +
4347
ProgressBar.create({id:'mana-bar', label:'⚡ ' + t('home_mana'), value:0, max:100, color:'#2196f3'}) +
4448
'<button class="help-tip-btn" aria-label="' + t('help_tip_mana') + '" ' +
4549
'title="' + t('help_tip_mana') + '" ' +
@@ -109,6 +113,13 @@ var HomeScreen = (function() {
109113
}
110114
}
111115

116+
function _scaleForDisplay(value, max, displayMax) {
117+
if (!max || max <= 0) return 0;
118+
var shown = Math.round(Math.max(0, value) * displayMax / max);
119+
if (shown > displayMax) shown = displayMax;
120+
return shown;
121+
}
122+
112123
function _renderWorldEventBanner(state, blockNum, t) {
113124
if (typeof WorldEvents === 'undefined') return '';
114125

app/js/ui/screens/settings.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var SettingsScreen = (function() {
4343
var highContrast = _getStoredBool('high_contrast', false);
4444
var reducedMotion = _getStoredBool('reduced_motion', false);
4545
var sfxVolume = Math.round(_getStoredNumber('sfx_volume', 0.5) * 100);
46+
var narratorEnabled = (typeof BattleNarrator !== 'undefined' && BattleNarrator.isEnabled) ? BattleNarrator.isEnabled() : _getStoredBool('battle_narrator', false);
4647
if (typeof SoundManager !== 'undefined') SoundManager.setVolume(sfxVolume / 100);
4748

4849
el.innerHTML =
@@ -63,7 +64,8 @@ var SettingsScreen = (function() {
6364
'<h2>' + t('settings_sound') + '</h2>' +
6465
_renderSlider('sfx-volume', t('settings_sfx'), sfxVolume) +
6566
_renderSlider('music-volume', t('settings_music'), 50) +
66-
_renderToggle('narrator-toggle', t('narrator_toggle'), true) +
67+
_renderToggle('narrator-toggle', t('narrator_toggle'), narratorEnabled) +
68+
'<button type="button" class="btn btn-secondary btn-sm" id="btn-test-narrator">' + t('narrator_test') + '</button>' +
6769
'<div class="settings-field">' +
6870
'<label for="sound-density" class="input-label">' + t('settings_sound_density') + '</label>' +
6971
'<select id="sound-density" class="input-field">' +
@@ -189,13 +191,30 @@ var SettingsScreen = (function() {
189191
}
190192
if (this.id === 'narrator-toggle' && typeof BattleNarrator !== 'undefined') {
191193
BattleNarrator.setEnabled(isActive);
194+
if (isActive) BattleNarrator.announce(Helpers.t('narrator_test_message'), 'assertive');
192195
}
193196
if (this.id === 'haptics-toggle') {
194197
_setStoredBool('haptics', isActive);
195198
}
196199
});
197200
}
198201

202+
// Narrator test
203+
var narratorTest = el.querySelector('#btn-test-narrator');
204+
if (narratorTest) narratorTest.addEventListener('click', function() {
205+
SoundManager.play('tap');
206+
if (typeof BattleNarrator !== 'undefined') {
207+
BattleNarrator.setEnabled(true);
208+
var toggle = el.querySelector('#narrator-toggle');
209+
if (toggle) {
210+
toggle.classList.add('active');
211+
toggle.setAttribute('aria-checked', 'true');
212+
}
213+
BattleNarrator.announce(Helpers.t('narrator_test_message'), 'assertive');
214+
BattleNarrator.spatialHint('center', 660);
215+
}
216+
});
217+
199218
// Realm info
200219
var realmBtn = el.querySelector('#btn-realm-info');
201220
if (realmBtn) realmBtn.addEventListener('click', function() {

app/sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Viz Magic — Service Worker
2-
var CACHE_NAME = 'viz-magic-v31';
2+
var CACHE_NAME = 'viz-magic-v32';
33
var ASSETS = [
44
'/',
55
'/index.html',

0 commit comments

Comments
 (0)