Skip to content

Commit 0e5d0fb

Browse files
author
web3blind
committed
Polish hunt rest marketplace and icons
1 parent 8007af0 commit 0e5d0fb

10 files changed

Lines changed: 137 additions & 41 deletions

File tree

app/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120
<script src="js/config.js?v=20260712a"></script>
121121

122122
<!-- I18n -->
123-
<script src="js/i18n/ru.js?v=20260713d"></script>
124-
<script src="js/i18n/en.js?v=20260713d"></script>
123+
<script src="js/i18n/ru.js?v=20260713e"></script>
124+
<script src="js/i18n/en.js?v=20260713e"></script>
125125

126126
<!-- Utilities -->
127127
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -179,23 +179,23 @@
179179
<script src="js/ui/components/progress-bar.js?v=20260712b"></script>
180180
<script src="js/ui/components/toast.js?v=20260711b"></script>
181181
<script src="js/ui/components/modal.js"></script>
182-
<script src="js/ui/components/nav.js?v=20260712b"></script>
182+
<script src="js/ui/components/nav.js?v=20260713a"></script>
183183
<script src="js/ui/components/battle-narrator.js?v=20260713a"></script>
184184

185185
<!-- UI Screens -->
186186
<script src="js/ui/screens/landing.js"></script>
187187
<script src="js/ui/screens/login.js?v=20260711a"></script>
188188
<script src="js/ui/screens/onboarding.js"></script>
189-
<script src="js/ui/screens/home.js?v=20260713c"></script>
189+
<script src="js/ui/screens/home.js?v=20260713d"></script>
190190
<script src="js/ui/screens/character.js?v=20260713b"></script>
191-
<script src="js/ui/screens/hunt.js?v=20260713b"></script>
191+
<script src="js/ui/screens/hunt.js?v=20260713c"></script>
192192
<script src="js/ui/screens/inventory.js?v=20260621l"></script>
193193
<script src="js/ui/screens/chronicle.js?v=20260712a"></script>
194194
<script src="js/ui/screens/duel.js"></script>
195195
<script src="js/ui/screens/arena.js?v=20260621d"></script>
196196
<script src="js/ui/screens/guild.js?v=20260621l"></script>
197197
<script src="js/ui/screens/map.js?v=20260621h"></script>
198-
<script src="js/ui/screens/marketplace.js?v=20260621k"></script>
198+
<script src="js/ui/screens/marketplace.js?v=20260713a"></script>
199199
<script src="js/ui/screens/crafting.js?v=20260621j"></script>
200200
<script src="js/ui/screens/quests.js?v=20260712a"></script>
201201
<script src="js/ui/screens/world-boss.js"></script>

app/js/i18n/en.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ var LangEN = {
597597
market_nothing_to_sell: 'Nothing to sell.',
598598
market_set_price: 'Set price',
599599
market_price_placeholder: 'Price',
600+
market_set_quantity: 'Quantity',
601+
market_listed_count: 'Items listed: {count}.',
602+
market_list_partial_error: 'Some items were listed ({count}), then an error occurred.',
600603
market_list_item: 'List',
601604
market_listed: 'Item listed on the bazaar!',
602605
market_pending_listing: 'pending confirmation',

app/js/i18n/ru.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ var LangRU = {
597597
market_nothing_to_sell: 'Нечего продавать.',
598598
market_set_price: 'Установить цену',
599599
market_price_placeholder: 'Цена',
600+
market_set_quantity: 'Количество',
601+
market_listed_count: 'Выставлено предметов: {count}.',
602+
market_list_partial_error: 'Часть предметов выставлена ({count}), затем произошла ошибка.',
600603
market_list_item: 'Выставить',
601604
market_listed: 'Товар выставлен на базар!',
602605
market_pending_listing: 'ожидает подтверждения',

app/js/ui/components/nav.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var NavComponent = (function() {
1313

1414
var tabs = [
1515
{ id: 'home', icon: '\uD83C\uDFE0', label: t('nav_home') },
16-
{ id: 'hunt', icon: '\u2694\uFE0F', label: t('nav_hunt') },
16+
{ id: 'hunt', icon: '\uD83C\uDFF9', label: t('nav_hunt') },
1717
{ id: 'map', icon: '\uD83D\uDDFA\uFE0F', label: t('nav_map') },
1818
{ id: 'guild', icon: '\uD83D\uDEE1\uFE0F', label: t('nav_guild') },
1919
{ id: 'marketplace', icon: '\uD83C\uDFEA', label: t('nav_bazaar') },

app/js/ui/screens/home.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ var HomeScreen = (function() {
256256
function _iconForScreen(screen) {
257257
var icons = {
258258
home: '\uD83C\uDFE0',
259-
hunt: '\u2694\uFE0F',
259+
hunt: '\uD83C\uDFF9',
260260
map: '\uD83D\uDDFA\uFE0F',
261261
guild: '\uD83D\uDEE1\uFE0F',
262262
marketplace: '\uD83C\uDFEA',

app/js/ui/screens/hunt.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var HuntScreen = (function() {
77
var selectedCreature = null;
88
var selectedSpell = null;
99
var stoneItemId = null;
10+
var HUNT_HP_DISPLAY_MAX = 5000;
1011

1112
function render() {
1213
var t = Helpers.t;
@@ -32,7 +33,8 @@ var HuntScreen = (function() {
3233
selectedSpell = null;
3334

3435
var needsRest = ch && ch.maxHp && ch.hp < ch.maxHp;
35-
var hpText = ch && ch.maxHp ? (Helpers.formatNumber(ch.hp || 0) + ' / ' + Helpers.formatNumber(ch.maxHp)) : '';
36+
var hpShown = ch && ch.maxHp ? _scaleForDisplay(ch.hp || 0, ch.maxHp, HUNT_HP_DISPLAY_MAX) : 0;
37+
var hpText = ch && ch.maxHp ? (Helpers.formatNumber(hpShown) + ' / ' + Helpers.formatNumber(HUNT_HP_DISPLAY_MAX)) : '';
3638
var html = '<div class="hunt-screen">' +
3739
'<h1>' + t('hunt_title') + '</h1>' +
3840
'<section class="hunt-rest-section" aria-label="' + t('hunt_rest_title') + '">' +
@@ -123,6 +125,13 @@ var HuntScreen = (function() {
123125
_bindEvents(el);
124126
}
125127

128+
function _scaleForDisplay(value, max, displayMax) {
129+
if (!max || max <= 0) return 0;
130+
var shown = Math.round(Math.max(0, value) * displayMax / max);
131+
if (shown > displayMax) shown = displayMax;
132+
return shown;
133+
}
134+
126135
function _filterCreaturesForLevel(creatures, character) {
127136
if (!character || !creatures || !creatures.length) return creatures || [];
128137
var level = character.level || 1;

app/js/ui/screens/marketplace.js

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,23 @@ var MarketplaceScreen = (function() {
210210
if (sellableItems.length === 0) {
211211
html += '<div class="empty-state">' + t('market_nothing_to_sell') + '</div>';
212212
} else {
213+
var sellGroups = _groupSellableItems(sellableItems);
213214
html += '<div class="market-sell-list" role="list">';
214-
for (var j = 0; j < sellableItems.length; j++) {
215-
var sItem = sellableItems[j];
215+
for (var j = 0; j < sellGroups.length; j++) {
216+
var group = sellGroups[j];
217+
var sItem = group.items[0];
216218
var sName = t('item_' + sItem.type) || sItem.type.replace(/_/g, ' ');
217219
var sRarity = ItemSystem.getRarityInfo(sItem.rarity);
220+
var itemIds = group.items.map(function(it) { return it.id; }).join(',');
218221
html += '<div class="market-sell-item ' + Helpers.rarityClass(sItem.rarity) + '" role="listitem" data-item="' + sItem.id + '">';
219-
html += '<span class="sell-item-name rarity-color-' + sRarity.name + '">' + sRarity.symbol + ' ' + Helpers.escapeHtml(sName) + '</span>';
222+
html += '<span class="sell-item-name rarity-color-' + sRarity.name + '">' + sRarity.symbol + ' ' + Helpers.escapeHtml(sName) +
223+
(group.items.length > 1 ? ' <span class="sell-item-count">×' + group.items.length + '</span>' : '') + '</span>';
220224
html += '<div class="sell-item-controls">';
221225
html += '<label for="price-' + sItem.id + '" class="sr-only">' + t('market_set_price') + '</label>';
222226
html += '<input type="number" id="price-' + sItem.id + '" class="input-field sell-price-input" min="1" placeholder="' + t('market_price_placeholder') + '" aria-label="' + t('market_set_price') + '">';
223-
html += '<button class="btn btn-primary btn-sm market-list-btn" data-item="' + sItem.id + '">' + t('market_list_item') + '</button>';
227+
html += '<label for="qty-' + sItem.id + '" class="sr-only">' + t('market_set_quantity') + '</label>';
228+
html += '<input type="number" id="qty-' + sItem.id + '" class="input-field sell-qty-input" min="1" max="' + group.items.length + '" value="1" aria-label="' + t('market_set_quantity') + '">';
229+
html += '<button class="btn btn-primary btn-sm market-list-btn" data-item="' + sItem.id + '" data-items="' + itemIds + '">' + t('market_list_item') + '</button>';
224230
html += '</div>';
225231
html += '</div>';
226232
}
@@ -325,8 +331,8 @@ var MarketplaceScreen = (function() {
325331
var listBtns = container.querySelectorAll('.market-list-btn');
326332
for (var l = 0; l < listBtns.length; l++) {
327333
listBtns[l].addEventListener('click', function() {
328-
var itemId = this.getAttribute('data-item');
329-
_handleList(itemId, container);
334+
var itemIds = (this.getAttribute('data-items') || this.getAttribute('data-item') || '').split(',');
335+
_handleList(itemIds, container);
330336
});
331337
}
332338

@@ -414,11 +420,17 @@ var MarketplaceScreen = (function() {
414420
}
415421

416422
/**
417-
* Handle list item for sale
423+
* Handle list item(s) for sale. Identical inventory rows are grouped in the UI,
424+
* but the chain still receives one listing action per selected item.
418425
*/
419-
function _handleList(itemId, container) {
426+
function _handleList(itemIds, container) {
420427
var t = Helpers.t;
421-
var priceInput = container.querySelector('#price-' + itemId);
428+
itemIds = itemIds || [];
429+
if (typeof itemIds === 'string') itemIds = [itemIds];
430+
if (!itemIds.length || !itemIds[0]) return;
431+
432+
var firstId = itemIds[0];
433+
var priceInput = container.querySelector('#price-' + firstId);
422434
if (!priceInput) return;
423435

424436
var price = parseInt(priceInput.value, 10);
@@ -428,24 +440,42 @@ var MarketplaceScreen = (function() {
428440
return;
429441
}
430442

443+
var qtyInput = container.querySelector('#qty-' + firstId);
444+
var quantity = qtyInput ? parseInt(qtyInput.value, 10) : 1;
445+
if (!quantity || quantity <= 0) quantity = 1;
446+
if (quantity > itemIds.length) quantity = itemIds.length;
447+
var selectedIds = itemIds.slice(0, quantity);
431448
var user = typeof VizAccount !== 'undefined' ? VizAccount.getCurrentUser() : '';
432-
SoundManager.play('tap');
433-
MarketProtocol.broadcastList(itemId, price, 0, function(err, result) {
434-
if (err) {
435-
Toast.error(t('market_list_error'));
436-
SoundManager.play('error');
437-
} else {
449+
var listed = 0;
450+
451+
function listNext(index) {
452+
if (index >= selectedIds.length) {
453+
Toast.success(t('market_listed_count', { count: listed }));
454+
SoundManager.play('success');
455+
render();
456+
return;
457+
}
458+
var itemId = selectedIds[index];
459+
MarketProtocol.broadcastList(itemId, price, 0, function(err, result) {
460+
if (err) {
461+
Toast.error(t(listed > 0 ? 'market_list_partial_error' : 'market_list_error', { count: listed }));
462+
SoundManager.play('error');
463+
render();
464+
return;
465+
}
438466
var blockNum = _resultBlockNum(result);
439467
if (user && StateEngine.processMarketListResult(user, itemId, price, 0, blockNum)) {
440468
StateEngine.saveCheckpoint(function() {});
441469
} else {
442470
_addPendingListing(itemId, price, result);
443471
}
444-
Toast.success(t('market_listed'));
445-
SoundManager.play('success');
446-
render();
447-
}
448-
});
472+
listed++;
473+
listNext(index + 1);
474+
});
475+
}
476+
477+
SoundManager.play('tap');
478+
listNext(0);
449479
}
450480

451481
function _resultBlockNum(result) {
@@ -489,6 +519,31 @@ var MarketplaceScreen = (function() {
489519
return true;
490520
}
491521

522+
function _groupSellableItems(items) {
523+
var byKey = {};
524+
var groups = [];
525+
for (var i = 0; i < items.length; i++) {
526+
var item = items[i];
527+
var key = _sellGroupKey(item);
528+
if (!byKey[key]) {
529+
byKey[key] = { key: key, items: [] };
530+
groups.push(byKey[key]);
531+
}
532+
byKey[key].items.push(item);
533+
}
534+
return groups;
535+
}
536+
537+
function _sellGroupKey(item) {
538+
var stats = item.stats || {};
539+
var statKeys = ['pot', 'res', 'swf', 'int', 'for_'];
540+
var statBits = [];
541+
for (var i = 0; i < statKeys.length; i++) {
542+
statBits.push(statKeys[i] + ':' + (stats[statKeys[i]] || 0));
543+
}
544+
return [item.type, item.rarity || 1, statBits.join('|')].join('::');
545+
}
546+
492547
function _isPendingItem(itemId) {
493548
for (var ref in pendingListings) {
494549
if (pendingListings.hasOwnProperty(ref) && pendingListings[ref].itemRef === itemId) {

app/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"short_name": "VizMagic",
44
"description": "Viz Magic — accessible browser RPG on the VIZ blockchain",
55
"id": "https://vizmagic.web3blind.xyz/",
6-
"start_url": "/?pwa=viz-magic-v52",
6+
"start_url": "/?pwa=viz-magic-v53",
77
"scope": "/",
88
"display": "standalone",
99
"display_override": ["standalone", "minimal-ui"],

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-v52';
2+
var CACHE_NAME = 'viz-magic-v53';
33
var ASSETS = [
44
'/',
55
'/index.html',

0 commit comments

Comments
 (0)