From f146f61caf4444f06810255e4d1b6f3f51e313aa Mon Sep 17 00:00:00 2001 From: Adi <6841988+DeepSpace2@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:11:29 +0200 Subject: [PATCH 1/3] feat: show word length --- internal/frontend/lobby.js | 47 +++++++++++++------ internal/frontend/resources/lobby.css | 65 ++++++++++++++++++++++++-- internal/frontend/templates/lobby.html | 4 +- 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/internal/frontend/lobby.js b/internal/frontend/lobby.js index 6b6f0150..d4192fda 100644 --- a/internal/frontend/lobby.js +++ b/internal/frontend/lobby.js @@ -92,20 +92,22 @@ function hideMenu() { menu.hidePopover(); } -// Since chromes implementation of the popup is dumb, we can't position -// it correctly without javascript. -if (!navigator.userAgent.toLowerCase().includes("firefox")) { - const menu_button = document.getElementById("menu-button"); - menu.addEventListener("toggle", (event) => { - if (event.newState === "open") { - const bounds = menu_button.getBoundingClientRect(); - // Technically this won't correctly handle the scrolling - // position, but we'll cope for now. - menu.style.top = bounds.bottom + "px"; +const menu_button = document.getElementById("menu-button"); +menu.addEventListener("toggle", (event) => { + if (event.newState === "open") { + const bounds = menu_button.getBoundingClientRect(); + menu.style.top = bounds.bottom + "px"; + + // making sure the menu doesn't go off-screen + const menuWidth = menu.offsetWidth; + const viewportWidth = window.innerWidth; + if (bounds.left + menuWidth > viewportWidth) { + menu.style.left = (viewportWidth - menuWidth - 5) + "px"; + } else { menu.style.left = bounds.left + "px"; } - }); -} + } +}); function showDialog(id, title, contentNode, buttonBar) { hideMenu(); @@ -1601,8 +1603,11 @@ const applyWordHints = (wordHints, dummy) => { wordContainer.style.visibility = "hidden"; } + var wordLengths = []; + var count = 0; + wordContainer.replaceChildren( - ...wordHints.map((hint) => { + ...wordHints.map((hint, index) => { const hintSpan = document.createElement("span"); hintSpan.classList.add("hint"); if (hint.character === 0) { @@ -1615,6 +1620,16 @@ const applyWordHints = (wordHints, dummy) => { hintSpan.innerText = String.fromCharCode(hint.character); } + if (hint.character === 32) { + wordLengths.push(count); + count = 0; + } else if (index === wordHints.length - 1) { + count += 1; + wordLengths.push(count); + } else { + count += 1; + } + if (hint.revealed && isDrawer) { hintSpan.classList.add("hint-revealed"); } @@ -1622,6 +1637,12 @@ const applyWordHints = (wordHints, dummy) => { return hintSpan; }), ); + + const lengthHint = document.createElement("sub"); + lengthHint.classList.add("word-length-hint"); + lengthHint.setAttribute("dir", wordContainer.getAttribute("dir")); + lengthHint.innerText = `(${wordLengths.join(", ")})`; + wordContainer.appendChild(lengthHint); }; const set_dummy_word_hints = () => { diff --git a/internal/frontend/resources/lobby.css b/internal/frontend/resources/lobby.css index a6c70f6b..fe5fa157 100644 --- a/internal/frontend/resources/lobby.css +++ b/internal/frontend/resources/lobby.css @@ -125,6 +125,7 @@ kbd { #lobby-header-center-element { display: flex; + justify-content: center; /* Hack to remove extra space between buttons */ font-size: 0; } @@ -160,6 +161,12 @@ kbd { overflow-x: hidden; } +.word-length-hint { + font-family: monospace; + font-size: 0.8rem; + padding-top: 0.4rem; +} + .hint-underline { border-bottom: 0.2rem black solid; padding-bottom: 0.1rem; @@ -663,11 +670,54 @@ kbd { } #lobby-header { - grid-template-columns: max-content auto max-content; - - grid-column-start: 1; + background-color: transparent; + display: grid; grid-column-end: 3; + grid-column-start: 1; + grid-gap: 5px; + grid-row: 1; + grid-template-columns: 1fr auto 1fr; + grid-template-rows: auto auto; + } + + #lobby-header-center-element { + display: contents; + } + + #menu-button-container { + grid-column: 2; + grid-row: 1; + background-color: white; + display: flex; + justify-content: center; + align-items: center; + padding: 0.1rem 0.2rem; + border-radius: var(--component-border-radius); + } + + #round-container { + grid-column: 1; + grid-row: 1; + justify-content: flex-start; + } + + #time-left { + grid-column: 3; grid-row: 1; + justify-content: flex-end; + } + + #word-container { + grid-column: 1 / 4; + grid-row: 2; + background-color: white; + align-items: center; + padding: 0.1rem 0.2rem; + border-radius: var(--component-border-radius); + column-gap: 0.2rem; + width: auto; + min-width: 0; + overflow: visible; } #round-container, @@ -722,9 +772,14 @@ kbd { } } +#menu-button-container { + position: relative; +} + #menu { - position: absolute; - inset: unset; + position: fixed; + margin: 0; + inset: auto; border: 1px solid gray; border-radius: var(--component-border-radius); } diff --git a/internal/frontend/templates/lobby.html b/internal/frontend/templates/lobby.html index 5f4cf08c..97610a0f 100644 --- a/internal/frontend/templates/lobby.html +++ b/internal/frontend/templates/lobby.html @@ -34,7 +34,7 @@