Skip to content

Commit b86ffdc

Browse files
author
web3blind
committed
Polish home install and ambient UX
1 parent c965aa5 commit b86ffdc

14 files changed

Lines changed: 114 additions & 43 deletions

File tree

app/assets/icons/viz-magic-192.png

49 Bytes
Loading

app/assets/icons/viz-magic-512.png

-120 Bytes
Loading

app/css/main.css

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,10 +1872,19 @@ body,
18721872
.developers-reward-options { display: grid; gap: 10px; margin-top: 12px; }
18731873

18741874

1875-
.temple-deity-fallback { display: inline-flex; align-items: center; justify-content: center; width: 72px; height: 72px; font-size: 2.5rem; margin: 0 auto 8px; }
1876-
.temple-deity-image { min-width: 72px; min-height: 72px; }
18771875
.boss-lore { margin: 16px 0; padding: 14px; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); text-align: left; }
18781876
.boss-lore h3 { margin-bottom: 8px; }
18791877
.boss-lore ul { margin: 8px 0 0 20px; }
18801878
.boss-motto { margin: 14px 0; padding-left: 12px; border-left: 3px solid var(--color-primary); color: var(--color-text); white-space: pre-line; }
18811879
.forecast-card-news { border-color: var(--color-accent); }
1880+
1881+
1882+
/* Low-cost ambient motion. Disabled for users who prefer reduced motion. */
1883+
@media (prefers-reduced-motion: no-preference) {
1884+
@keyframes vmagic-rune-pulse { 0%, 100% { filter: drop-shadow(0 0 0 rgba(255,216,88,0)); transform: scale(1); } 50% { filter: drop-shadow(0 0 8px rgba(255,216,88,0.45)); transform: scale(1.03); } }
1885+
@keyframes vmagic-boss-breathe { 0%, 100% { transform: scale(1); filter: drop-shadow(0 0 0 rgba(124,53,255,0)); } 50% { transform: scale(1.025); filter: drop-shadow(0 0 10px rgba(124,53,255,0.35)); } }
1886+
@keyframes vmagic-weather-drift { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
1887+
.recipe-icon, .craft-icon-anim { animation: vmagic-rune-pulse 3.6s ease-in-out infinite; }
1888+
.boss-icon-large { display: inline-block; animation: vmagic-boss-breathe 4.8s ease-in-out infinite; }
1889+
.magical-forecast .forecast-icon { display: inline-block; animation: vmagic-weather-drift 5.5s ease-in-out infinite; }
1890+
}

app/index.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
<title>Viz Magic</title>
1111
<link rel="manifest" href="manifest.json?v=20260713b">
1212
<link rel="icon" href="favicon.ico?v=20260712c">
13-
<link rel="icon" type="image/png" sizes="192x192" href="assets/icons/viz-magic-192.png?v=20260713a">
14-
<link rel="icon" type="image/png" sizes="512x512" href="assets/icons/viz-magic-512.png?v=20260713a">
15-
<link rel="apple-touch-icon" href="assets/icons/viz-magic-192.png?v=20260713a">
16-
<link rel="stylesheet" href="css/main.css?v=20260713c">
13+
<link rel="icon" type="image/png" sizes="192x192" href="assets/icons/viz-magic-192.png?v=20260714a">
14+
<link rel="icon" type="image/png" sizes="512x512" href="assets/icons/viz-magic-512.png?v=20260714a">
15+
<link rel="apple-touch-icon" href="assets/icons/viz-magic-192.png?v=20260714a">
16+
<link rel="stylesheet" href="css/main.css?v=20260714a">
1717
<link rel="stylesheet" href="css/themes.css">
1818
<link rel="stylesheet" href="css/accessibility.css">
1919
</head>
@@ -124,8 +124,8 @@
124124
<script src="js/config.js?v=20260712a"></script>
125125

126126
<!-- I18n -->
127-
<script src="js/i18n/ru.js?v=20260713i"></script>
128-
<script src="js/i18n/en.js?v=20260713i"></script>
127+
<script src="js/i18n/ru.js?v=20260714a"></script>
128+
<script src="js/i18n/en.js?v=20260714a"></script>
129129

130130
<!-- Utilities -->
131131
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -190,11 +190,11 @@
190190
<script src="js/ui/screens/landing.js"></script>
191191
<script src="js/ui/screens/login.js?v=20260711a"></script>
192192
<script src="js/ui/screens/onboarding.js"></script>
193-
<script src="js/ui/screens/home.js?v=20260713f"></script>
193+
<script src="js/ui/screens/home.js?v=20260714a"></script>
194194
<script src="js/ui/screens/character.js?v=20260713b"></script>
195195
<script src="js/ui/screens/hunt.js?v=20260713d"></script>
196196
<script src="js/ui/screens/inventory.js?v=20260713a"></script>
197-
<script src="js/ui/screens/chronicle.js?v=20260713a"></script>
197+
<script src="js/ui/screens/chronicle.js?v=20260714a"></script>
198198
<script src="js/ui/screens/duel.js"></script>
199199
<script src="js/ui/screens/arena.js?v=20260621d"></script>
200200
<script src="js/ui/screens/guild.js?v=20260621l"></script>
@@ -206,10 +206,10 @@
206206
<script src="js/ui/screens/settings.js?v=20260713b"></script>
207207
<script src="js/ui/screens/help.js?v=20260713a"></script>
208208
<script src="js/ui/screens/leaderboard.js?v=20260712c"></script>
209-
<script src="js/ui/screens/temple.js?v=20260713b"></script>
210-
<script src="js/ui/screens/developers.js?v=20260713a"></script>
209+
<script src="js/ui/screens/temple.js?v=20260714a"></script>
210+
<script src="js/ui/screens/developers.js?v=20260714a"></script>
211211

212212
<!-- Main App Controller (must be last) -->
213-
<script src="js/ui/app.js?v=20260713b"></script>
213+
<script src="js/ui/app.js?v=20260714a"></script>
214214
</body>
215215
</html>

app/js/i18n/en.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,11 @@ var LangEN = {
584584
developers_reward_confirm_button: 'Send reward',
585585
developers_reward_success: 'Thank you! Developer reward sent.',
586586
developers_reward_error: 'Could not send the reward. Check login and try again.',
587+
developers_custom_reward_label: 'Custom reward amount, % mana',
588+
developers_custom_reward_hint: 'Enter 0.01 to 100. Example: 0.25 or 3.',
589+
developers_custom_reward_button: 'Reward custom amount',
590+
developers_reward_invalid: 'Enter an amount from 0.01 to 100.',
591+
home_install_shortcut_requested: 'If the browser installed the shortcut, the game will say: “Shortcut installed.” If there is no message, open the browser menu and add the shortcut manually.',
587592
developers_reward_memo: 'thanks for Viz Magic',
588593

589594
// Marketplace
@@ -889,7 +894,7 @@ var LangEN = {
889894
event_next_season: 'Season Change',
890895

891896
magic_news_sun_wolf: 'A squad of battle mages met a sun wolf in the enchanted forest. The best healers of the Third Kingdom are treating the entire squad for temporary blindness.',
892-
magic_news_forest_patrol: 'The forest watch asks mages not to feed talking stumps with promises. The stumps write everything down.',
897+
magic_news_forest_patrol: 'The forest watch asks mages not to feed talking stumps with promises. They remember everything and demand a sequel...',
893898
magic_news_wand_union: 'The union of old wands announced a day of silence. Sparks are allowed only in whispers.',
894899
magic_news_frog_court: 'The Frog Court acquitted the rain: witnesses confirmed it was falling upward for a valid reason.',
895900
magic_news_dragon_shadow: 'The shadow of the Aether Dragon was seen near the map edge. The shadow claims it was only walking.',

app/js/i18n/ru.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,11 @@ var LangRU = {
584584
developers_reward_confirm_button: 'Отправить награду',
585585
developers_reward_success: 'Спасибо! Награда разработчику отправлена.',
586586
developers_reward_error: 'Не удалось отправить награду. Проверьте вход и попробуйте снова.',
587+
developers_custom_reward_label: 'Своя сумма награды, % маны',
588+
developers_custom_reward_hint: 'Введите от 0,01 до 100. Например: 0,25 или 3.',
589+
developers_custom_reward_button: 'Наградить своей суммой',
590+
developers_reward_invalid: 'Введите сумму от 0,01 до 100.',
591+
home_install_shortcut_requested: 'Если браузер установил ярлык, игра сообщит: «Ярлык установлен». Если сообщения нет, откройте меню браузера и добавьте ярлык вручную.',
587592
developers_reward_memo: 'спасибо за Viz Magic',
588593

589594
// Marketplace
@@ -889,7 +894,7 @@ var LangRU = {
889894
event_next_season: 'Смена Сезона',
890895

891896
magic_news_sun_wolf: 'Отряд боевых магов в зачарованном лесу наткнулся на солнечного волка. Временную слепоту всего отряда лечат лучшие знахари Третьего Царства.',
892-
magic_news_forest_patrol: 'Лесная стража просит не кормить говорящие пни обещаниями. Пни всё записывают и потом требуют продолжения.',
897+
magic_news_forest_patrol: 'Лесная стража просит не кормить говорящие пни обещаниями. Они всё запоминают и требуют продолжения...',
893898
magic_news_wand_union: 'Профсоюз старых жезлов объявил день тишины. Искры разрешены только шёпотом.',
894899
magic_news_frog_court: 'Жабий суд оправдал дождь: свидетели подтвердили, что он падал вверх по уважительной причине.',
895900
magic_news_dragon_shadow: 'Тень Эфирного Дракона замечена на границе карты. Сама тень утверждает, что просто гуляла.',

app/js/ui/app.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var App = (function() {
1515
var _syncVisible = false;
1616
var _lastSyncPercent = -1;
1717
var _deferredInstallPrompt = null;
18+
var INSTALL_ACK_KEY = VizMagicConfig.STORAGE_PREFIX + 'install_shortcut_ack';
1819
var POLL_INTERVAL_MS = 3000;
1920

2021
/**
@@ -28,6 +29,8 @@ var App = (function() {
2829
A11y.init();
2930
A11y.initKeyboardShortcuts();
3031

32+
_showPendingInstallNotice();
33+
3134
// Initialize Battle Narrator
3235
if (typeof BattleNarrator !== 'undefined') {
3336
BattleNarrator.init();
@@ -284,8 +287,9 @@ var App = (function() {
284287
});
285288
window.addEventListener('appinstalled', function() {
286289
_deferredInstallPrompt = null;
290+
try { localStorage.setItem(INSTALL_ACK_KEY, '1'); } catch (e) {}
287291
if (typeof Toast !== 'undefined') {
288-
Toast.success(Helpers.t('home_install_shortcut_installed'));
292+
Toast.success(Helpers.t('home_install_shortcut_installed'), 7000, { key: 'install_shortcut_installed' });
289293
}
290294
});
291295
if ('serviceWorker' in navigator) {
@@ -297,23 +301,38 @@ var App = (function() {
297301
}
298302
}
299303

304+
function _showPendingInstallNotice() {
305+
try {
306+
if (localStorage.getItem(INSTALL_ACK_KEY) === '1') {
307+
localStorage.removeItem(INSTALL_ACK_KEY);
308+
setTimeout(function() {
309+
if (typeof Toast !== 'undefined') Toast.success(Helpers.t('home_install_shortcut_installed'), 7000, { key: 'install_shortcut_installed' });
310+
}, 600);
311+
}
312+
} catch (e) {}
313+
}
314+
300315
function installShortcut() {
301316
if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) {
302317
if (typeof Toast !== 'undefined') Toast.info(Helpers.t('home_install_shortcut_already'), 5000, { key: 'install_shortcut_already' });
303318
return;
304319
}
305320
if (_deferredInstallPrompt) {
321+
if (typeof Toast !== 'undefined') Toast.info(Helpers.t('home_install_shortcut_requested'), 7000, { key: 'install_shortcut_requested' });
306322
_deferredInstallPrompt.prompt();
307323
_deferredInstallPrompt.userChoice.then(function(choice) {
308324
_deferredInstallPrompt = null;
309325
if (choice && choice.outcome === 'accepted' && typeof Toast !== 'undefined') {
310-
Toast.success(Helpers.t('home_install_shortcut_installed'));
326+
try { localStorage.setItem(INSTALL_ACK_KEY, '1'); } catch (e) {}
327+
Toast.success(Helpers.t('home_install_shortcut_installed'), 7000, { key: 'install_shortcut_installed' });
311328
} else {
329+
if (typeof Toast !== 'undefined') Toast.info(Helpers.t('home_install_shortcut_requested'), 7000, { key: 'install_shortcut_requested' });
312330
_showInstallInstructions();
313331
}
314332
});
315333
return;
316334
}
335+
if (typeof Toast !== 'undefined') Toast.info(Helpers.t('home_install_shortcut_requested'), 7000, { key: 'install_shortcut_requested' });
317336
_showInstallInstructions();
318337
}
319338

app/js/ui/screens/chronicle.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var ChronicleScreen = (function() {
1313
var REQUIRED_TAG = '#viz_magic';
1414
var cachedFeedHtml = {};
1515
var DRAFT_KEY = VizMagicConfig.STORAGE_PREFIX + 'chronicle_draft';
16+
var FEED_CACHE_PREFIX = VizMagicConfig.STORAGE_PREFIX + 'chronicle_feed_';
1617

1718
function render() {
1819
var t = Helpers.t;
@@ -62,6 +63,14 @@ var ChronicleScreen = (function() {
6263
try { localStorage.setItem(DRAFT_KEY, text || ''); } catch (e) {}
6364
}
6465

66+
function _getCachedFeed(tab) {
67+
try { return localStorage.getItem(FEED_CACHE_PREFIX + tab) || ''; } catch (e) { return ''; }
68+
}
69+
70+
function _setCachedFeed(tab, html) {
71+
try { localStorage.setItem(FEED_CACHE_PREFIX + tab, html || ''); } catch (e) {}
72+
}
73+
6574
function _tabButton(id, label) {
6675
var isActive = currentTab === id;
6776
return '<button class="btn ' + (isActive ? 'btn-primary' : 'btn-secondary') + ' btn-sm chronicle-tab-btn" ' +
@@ -122,6 +131,7 @@ var ChronicleScreen = (function() {
122131
var feed = Helpers.$('chronicle-feed');
123132
if (!feed) return;
124133

134+
if (!cachedFeedHtml[currentTab]) cachedFeedHtml[currentTab] = _getCachedFeed(currentTab);
125135
if (cachedFeedHtml[currentTab]) {
126136
feed.innerHTML = cachedFeedHtml[currentTab];
127137
_bindBlessButtons(feed);
@@ -300,6 +310,7 @@ var ChronicleScreen = (function() {
300310
}
301311
feed.innerHTML = html;
302312
cachedFeedHtml[currentTab] = html;
313+
_setCachedFeed(currentTab, html);
303314
_bindBlessButtons(feed);
304315
}
305316

app/js/ui/screens/developers.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ var DevelopersScreen = (function() {
2929
if (!user) {
3030
html += '<div class="empty-state">' + t('developers_login_required') + '</div>';
3131
} else {
32+
html += '<div class="developers-custom-reward">';
33+
html += '<label for="developers-custom-energy" class="input-label">' + t('developers_custom_reward_label') + '</label>';
34+
html += '<input id="developers-custom-energy" class="input-field" type="number" min="0.01" max="100" step="0.01" inputmode="decimal" placeholder="0.25">';
35+
html += '<p class="developers-note">' + t('developers_custom_reward_hint') + '</p>';
36+
html += '<button type="button" class="btn btn-primary dev-custom-reward-btn">' + t('developers_custom_reward_button') + '</button>';
37+
html += '</div>';
3238
html += '<div class="developers-reward-options" role="group" aria-label="' + t('developers_reward_title') + '">';
3339
for (var i = 0; i < REWARD_OPTIONS.length; i++) {
3440
html += '<button type="button" class="btn btn-primary dev-reward-btn" data-energy="' + REWARD_OPTIONS[i] + '">' +
@@ -43,6 +49,20 @@ var DevelopersScreen = (function() {
4349
}
4450

4551
function _bindEvents(el) {
52+
var customBtn = el.querySelector('.dev-custom-reward-btn');
53+
if (customBtn) {
54+
customBtn.addEventListener('click', function() {
55+
var input = el.querySelector('#developers-custom-energy');
56+
var percent = input ? parseFloat(String(input.value || '').replace(',', '.')) : 0;
57+
if (!(percent >= 0.01 && percent <= 100)) {
58+
Toast.error(Helpers.t('developers_reward_invalid'));
59+
SoundManager.play('error');
60+
return;
61+
}
62+
_confirmReward(Math.round(percent * 100));
63+
});
64+
}
65+
4666
var buttons = el.querySelectorAll('.dev-reward-btn');
4767
for (var i = 0; i < buttons.length; i++) {
4868
buttons[i].addEventListener('click', function() {

app/js/ui/screens/home.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
var HomeScreen = (function() {
66
'use strict';
77

8-
var PRIMARY_HOME_SCREENS = ['home', 'hunt', 'map', 'inventory', 'arena', 'quests', 'guild', 'marketplace', 'crafting', 'temple'];
8+
var PRIMARY_HOME_SCREENS = ['home', 'inventory', 'guild', 'crafting', 'hunt', 'map', 'arena', 'quests', 'marketplace', 'temple'];
99
var SECONDARY_HOME_SCREENS = ['chronicle', 'character', 'leaderboard', 'world-boss', 'settings', 'help', 'developers'];
1010
var HOME_HP_DISPLAY_MAX = 5000;
1111
var HOME_XP_DISPLAY_MAX = 3000;

0 commit comments

Comments
 (0)