From a05a10efd7a9d359cc2fe5e6f44592ec20d7a920 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Fri, 10 Jul 2026 08:46:38 -0400 Subject: [PATCH] fix(ui): tavern floor, play-area focus border, and Smirk locked-wallet UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tavern: revert the per-cell 'varied floor/wall' tiles to coherent single tiles — mixing wood/stone/plank per cell read as visual noise (assetPacks.js). Play area: draw the keyboard-focus outline inset (outline-offset -2px) so the yellow border shows on the right edge, which the container's overflow:hidden was clipping (ui.js). Smirk: a locked wallet now shows a friendly 'unlock in the extension, then Retry' hint instead of a red error, and the LOCKED error code is preserved through connect()/signMessage(). Current Smirk builds auto-open the unlock popup on connect(); older builds throw LOCKED, which the Retry button re-invokes (smirkAuth.js). --- html/js/network/smirkAuth.js | 25 +++++++++++++++++++------ html/js/render/assetPacks.js | 17 ++++++++--------- html/js/ui/ui.js | 5 ++++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/html/js/network/smirkAuth.js b/html/js/network/smirkAuth.js index 5e6de09..d9dbde6 100644 --- a/html/js/network/smirkAuth.js +++ b/html/js/network/smirkAuth.js @@ -170,7 +170,9 @@ const SmirkAuth = { try { keys = await window.smirk.connect(); } catch (smirkError) { - throw new Error('Failed to connect to Smirk wallet: ' + (smirkError.message || 'Unknown error')); + const e = new Error('Failed to connect to Smirk wallet: ' + (smirkError.message || 'Unknown error')); + e.code = smirkError && smirkError.code; // preserve SmirkRpcError code ('LOCKED', 'USER_REJECTED', …) + throw e; } if (!keys || !keys.wow) { @@ -182,7 +184,9 @@ const SmirkAuth = { try { signResult = await window.smirk.signMessage(challenge); } catch (signError) { - throw new Error('Failed to sign challenge: ' + (signError.message || 'Unknown error')); + const e = new Error('Failed to sign challenge: ' + (signError.message || 'Unknown error')); + e.code = signError && signError.code; // preserve 'LOCKED' etc. + throw e; } // Find WOW signature @@ -317,11 +321,20 @@ const SmirkAuth = { } catch (err) { console.error('Smirk login failed:', err); - this._updateButton(btn, 'error'); + this._updateButton(btn, 'error'); // button label becomes "Retry Smirk Connect" - // Show error message - const errorMsg = 'Smirk login failed: ' + err.message; - $('#messages').append($('
  • ').text(errorMsg)); + // A locked wallet is an action, not a red error. Current Smirk builds auto-open the + // unlock popup on connect()/signNostrEvent(); older builds throw LOCKED — so guide the + // user to unlock and retry (the Retry button re-invokes connect(), which pops the + // unlock screen on the updated build). + const locked = (err && err.code === 'LOCKED') || /is locked/i.test((err && err.message) || ''); + if (locked) { + $('#messages').append($('
  • ').text( + '🔒 Your Smirk wallet is locked. Open the Smirk extension, unlock it, then click "Retry Smirk Connect".' + )); + } else { + $('#messages').append($('
  • ').text('Smirk login failed: ' + err.message)); + } throw err; } diff --git a/html/js/render/assetPacks.js b/html/js/render/assetPacks.js index d4bf965..8fc4ce3 100644 --- a/html/js/render/assetPacks.js +++ b/html/js/render/assetPacks.js @@ -112,16 +112,15 @@ tileset: { url: 'assets/kenney/roguelikeSheet.png', tile: 16, spacing: 1 }, // Default tile picks from the sheet metadata ( roguelikeSheet_meta.json). // The tile-picker overlay can override these per-user via localStorage. - // floor/wall are ARRAYS of [col,row] variants (sheet cols = 57): TileRenderer - // picks one deterministically per cell so a wall of stone doesn't read as a - // single flat texture. Single-pair kinds (bar/table/features) draw as-is. + // Each kind maps to a single [col,row] on the sheet (cols = 57). Per-cell "variant" + // arrays were tried but mixing wood/stone/plank tiles per cell read as noise, so we + // keep one coherent tile per kind. (TileRenderer still accepts an array here if a + // future theme wants subtle, same-material variation.) tiles: { - // floor: sheet 119/120 (wood/stone) + 982-984 (planks) - floor: [[5, 2], [6, 2], [13, 17], [14, 17], [15, 17]], - floor2: [[6, 2], [13, 17], [15, 17]], - // wall: sheet 697-701 + 868/869/871-874 (stone masonry) - wall: [[13, 12], [14, 12], [15, 12], [16, 12], [17, 12], - [13, 15], [14, 15], [16, 15], [17, 15], [18, 15], [19, 15]], + floor: [5, 2], // tile 119 — wood floor (uniform) + floor2: [6, 2], // tile 120 — stone floor (accent) + wall: [13, 12], // tile 697 — stone masonry + bar: [28, 0], // tile 28 — counter table: [20, 3], // tile 191 — table // Dungeon features drawn as real tiles instead of monospace glyphs. diff --git a/html/js/ui/ui.js b/html/js/ui/ui.js index 30fcdc0..53b9af3 100644 --- a/html/js/ui/ui.js +++ b/html/js/ui/ui.js @@ -19,7 +19,10 @@ const UI = { var chatInput = $('#chatInput'); if (document.activeElement === gameDisplay[0]) { - gameDisplay.css('outline', '2px solid yellow'); + // Inset the outline (offset -2px) so it is drawn INSIDE the box — the play area is + // flush to the viewport's right edge and the container clips an outward outline there, + // which hid the border on the right side. + gameDisplay.css({ 'outline': '2px solid yellow', 'outline-offset': '-2px' }); chatInput.css('outline', 'none'); } else if (document.activeElement === chatInput[0]) { chatInput.css('outline', '2px solid cyan');