Skip to content

Commit 31413ca

Browse files
committed
Improve guild, inventory, and duel UX
1 parent 3dcd1bb commit 31413ca

7 files changed

Lines changed: 550 additions & 57 deletions

File tree

app/js/i18n/en.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ var LangEN = {
155155
hunt_damage_dealt: 'Damage dealt',
156156
hunt_damage_taken: 'Damage taken',
157157
arena_incoming_challenges: 'Incoming Challenges',
158+
arena_incoming_duel_toast: '{opponent} challenges you to a duel. Opening arena.',
159+
arena_open_challenge: 'Open arena',
160+
arena_duel_accepted_toast: 'Challenge accepted. You can continue the duel now.',
161+
arena_open_duel: 'Open duel',
158162
hunt_again: 'Hunt again',
159163
hunt_home: 'Home',
160164
hunt_equip_now: 'Equip now',
@@ -180,6 +184,17 @@ var LangEN = {
180184
inv_sell: 'Sell',
181185
inv_use: 'Use',
182186
inv_empty: 'Bag is empty.',
187+
inv_count: 'Count',
188+
inv_filters: 'Bag filters',
189+
inv_filter_all: 'All',
190+
inv_filter_equipment: 'Equipment',
191+
inv_filter_materials: 'Materials',
192+
inv_filter_consumables: 'Consumables',
193+
inv_sort: 'Sort',
194+
inv_sort_rarity_desc: 'Rarest first',
195+
inv_sort_name_asc: 'By name',
196+
inv_sort_count_desc: 'Largest stacks first',
197+
inv_compact_mode: 'Compact mode',
183198

184199
// Chronicle
185200
chronicle_title: 'World Chronicle',
@@ -391,14 +406,27 @@ var LangEN = {
391406
guild_recruit_target: 'Mage name',
392407
guild_invite_send: 'Send Invite',
393408
guild_invite_sent: 'Invite sent!',
409+
guild_invite_received: 'You received a guild invite. Opening the guild screen.',
410+
guild_pending_invites: 'Pending Invites',
411+
guild_accept_invite: 'Accept Invite',
412+
guild_invited_by: 'Invited by',
394413
guild_promote: 'Promote',
395414
guild_promoted: 'Rank changed!',
415+
guild_rank_changed_notice: 'Your guild rank changed. Opening the guild screen.',
396416
guild_choose_rank: 'Choose rank',
397417
guild_treasury: 'Treasury',
398418
guild_treasury_account: 'Treasury account',
399419
guild_tithe_rate: 'Tithe rate',
400420
guild_total_delegated: 'Total delegated',
401421
guild_settings: 'Settings',
422+
guild_settings_view_only: 'This screen shows the current guild settings.',
423+
guild_settings_officer_hint: 'This view now exposes the main guild settings and summary.',
424+
guild_membership_mode: 'Membership mode',
425+
guild_membership_open: 'Open',
426+
guild_membership_approval: 'Approval required',
427+
guild_membership_invite: 'Invite only',
428+
guild_min_shares: 'Minimum SHARES to join',
429+
guild_notification_open_guild: 'Open guild',
402430
guild_id_label: 'Guild ID',
403431
guild_name_label: 'Name',
404432
guild_tag_label: 'Tag (2-5 chars)',
@@ -876,4 +904,3 @@ var LangEN = {
876904
char_hp_explainer: 'HP grows from level, Resilience, and class. Full formula is in the Guide.',
877905
help_close: 'Got it'
878906
};
879-

app/js/i18n/ru.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ var LangRU = {
155155
hunt_damage_dealt: 'Нанесено урона',
156156
hunt_damage_taken: 'Получено урона',
157157
arena_incoming_challenges: 'Входящие вызовы',
158+
arena_incoming_duel_toast: '{opponent} вызывает вас на дуэль. Открываю арену.',
159+
arena_open_challenge: 'Открыть арену',
160+
arena_duel_accepted_toast: 'Вызов принят. Можно продолжать дуэль.',
161+
arena_open_duel: 'Открыть дуэль',
158162
hunt_again: 'Охотиться снова',
159163
hunt_home: 'Домой',
160164
hunt_equip_now: 'Экипировать сейчас',
@@ -180,6 +184,17 @@ var LangRU = {
180184
inv_sell: 'Продать',
181185
inv_use: 'Использовать',
182186
inv_empty: 'Сумка пуста.',
187+
inv_count: 'Количество',
188+
inv_filters: 'Фильтры сумки',
189+
inv_filter_all: 'Всё',
190+
inv_filter_equipment: 'Экипировка',
191+
inv_filter_materials: 'Материалы',
192+
inv_filter_consumables: 'Расходники',
193+
inv_sort: 'Сортировка',
194+
inv_sort_rarity_desc: 'Сначала редкие',
195+
inv_sort_name_asc: 'По названию',
196+
inv_sort_count_desc: 'Сначала большие стаки',
197+
inv_compact_mode: 'Компактный режим',
183198

184199
// Chronicle
185200
chronicle_title: 'Хроника Мира',
@@ -391,14 +406,27 @@ var LangRU = {
391406
guild_recruit_target: 'Имя мага',
392407
guild_invite_send: 'Отправить приглашение',
393408
guild_invite_sent: 'Приглашение отправлено!',
409+
guild_invite_received: 'Вас пригласили в гильдию. Открываю раздел гильдии.',
410+
guild_pending_invites: 'Ожидающие приглашения',
411+
guild_accept_invite: 'Принять приглашение',
412+
guild_invited_by: 'Пригласил',
394413
guild_promote: 'Повысить',
395414
guild_promoted: 'Ранг изменён!',
415+
guild_rank_changed_notice: 'Ваш ранг в гильдии изменён. Открываю раздел гильдии.',
396416
guild_choose_rank: 'Выберите ранг',
397417
guild_treasury: 'Казна',
398418
guild_treasury_account: 'Счёт казны',
399419
guild_tithe_rate: 'Ставка десятины',
400420
guild_total_delegated: 'Всего делегировано',
401421
guild_settings: 'Настройки',
422+
guild_settings_view_only: 'Здесь показаны текущие настройки гильдии.',
423+
guild_settings_officer_hint: 'Сейчас здесь доступны основные настройки и сводка гильдии.',
424+
guild_membership_mode: 'Режим вступления',
425+
guild_membership_open: 'Свободный вход',
426+
guild_membership_approval: 'По одобрению',
427+
guild_membership_invite: 'Только по приглашению',
428+
guild_min_shares: 'Минимум SHARES для вступления',
429+
guild_notification_open_guild: 'Открыть гильдию',
402430
guild_id_label: 'ID гильдии',
403431
guild_name_label: 'Название',
404432
guild_tag_label: 'Тег (2-5 символов)',
@@ -876,4 +904,3 @@ var LangRU = {
876904
char_hp_explainer: 'HP растёт от уровня, Стойкости и класса. Подробная формула — в Справке.',
877905
help_close: 'Понятно'
878906
};
879-

app/js/ui/components/toast.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,45 @@ var Toast = (function() {
2323
* @param {string} [type] - 'info', 'success', 'error', 'warning'
2424
* @param {number} [duration] - ms (default 3000)
2525
*/
26-
function show(message, type, duration) {
26+
function show(message, type, duration, options) {
2727
type = type || 'info';
2828
duration = duration || 3000;
29+
options = options || {};
2930

3031
var toast = document.createElement('div');
3132
toast.className = 'toast toast-' + type;
3233
toast.textContent = message;
3334
toast.setAttribute('role', 'alert');
3435

36+
if (options.actionLabel) {
37+
toast.setAttribute('tabindex', '0');
38+
toast.setAttribute('aria-label', message + '. ' + options.actionLabel);
39+
}
40+
3541
_getContainer().appendChild(toast);
3642
A11y.announce(message);
3743

44+
if (typeof options.onClick === 'function') {
45+
toast.addEventListener('click', function() {
46+
options.onClick();
47+
});
48+
toast.addEventListener('keydown', function(e) {
49+
if (e.key === 'Enter' || e.key === ' ') {
50+
e.preventDefault();
51+
options.onClick();
52+
}
53+
});
54+
}
55+
3856
// Animate in
3957
requestAnimationFrame(function() {
4058
toast.classList.add('show');
4159
});
4260

61+
if (duration <= 0) {
62+
return toast;
63+
}
64+
4365
// Auto-dismiss
4466
setTimeout(function() {
4567
toast.classList.remove('show');
@@ -49,9 +71,9 @@ var Toast = (function() {
4971
}, duration);
5072
}
5173

52-
function success(msg) { show(msg, 'success'); }
53-
function error(msg) { show(msg, 'error', 4000); }
54-
function info(msg) { show(msg, 'info'); }
74+
function success(msg, duration, options) { show(msg, 'success', duration || 3000, options); }
75+
function error(msg, duration, options) { show(msg, 'error', duration || 4000, options); }
76+
function info(msg, duration, options) { show(msg, 'info', duration || 3000, options); }
5577

5678
return { show: show, success: success, error: error, info: info };
5779
})();

app/js/ui/screens/arena.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ var ArenaScreen = (function() {
77

88
var currentTab = 'leaderboard'; // leaderboard, history
99
var levelFilter = 'all';
10+
var listenersRegistered = false;
11+
var seenIncomingRefs = {};
1012

1113
function render() {
14+
_ensureEventListeners();
15+
1216
var t = Helpers.t;
1317
var el = Helpers.$('screen-arena');
1418
if (!el) return;
@@ -69,6 +73,48 @@ var ArenaScreen = (function() {
6973
_scanIncomingChallenges(el);
7074
}
7175

76+
function _ensureEventListeners() {
77+
if (listenersRegistered) return;
78+
listenersRegistered = true;
79+
80+
Helpers.EventBus.on('duel_challenge', function(data) {
81+
var user = VizAccount.getCurrentUser();
82+
if (!data || !user) return;
83+
if (data.target !== user) return;
84+
85+
var ref = String(data.challengeRef || data.combatRef || '');
86+
if (ref && seenIncomingRefs[ref]) return;
87+
if (ref) seenIncomingRefs[ref] = true;
88+
89+
Toast.info(Helpers.t('arena_incoming_duel_toast', {
90+
opponent: data.account || data.challenger || ''
91+
}), 7000, {
92+
actionLabel: Helpers.t('arena_open_challenge'),
93+
onClick: function() {
94+
currentTab = 'history';
95+
Helpers.EventBus.emit('navigate', 'arena');
96+
}
97+
});
98+
99+
currentTab = 'history';
100+
Helpers.EventBus.emit('navigate', 'arena');
101+
});
102+
103+
Helpers.EventBus.on('duel_accepted', function(data) {
104+
var user = VizAccount.getCurrentUser();
105+
if (!data || !user) return;
106+
if (data.challenger !== user && data.target !== user) return;
107+
108+
Toast.success(Helpers.t('arena_duel_accepted_toast'), 5000, {
109+
actionLabel: Helpers.t('arena_open_duel'),
110+
onClick: function() {
111+
var opp = data.challenger === user ? data.target : data.challenger;
112+
DuelScreen.startDuel(opp, String(data.combatRef || ''), { source: 'accepted_event' });
113+
}
114+
});
115+
});
116+
}
117+
72118
/**
73119
* Scan recent VM operations to find challenges targeting the current user.
74120
* Uses custom_protocol_api to walk backward through challenger's VM chain.
@@ -383,5 +429,7 @@ var ArenaScreen = (function() {
383429
}
384430
}
385431

432+
_ensureEventListeners();
433+
386434
return { render: render };
387435
})();

0 commit comments

Comments
 (0)