From b7d469a06e30c83d332509e3322683713710c32f Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Wed, 3 Jun 2026 23:14:51 +0200 Subject: [PATCH] Stage 8 polish: keyboard-aware modals, consistent select pickers, required game type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third owner-review pass (iPhone): - Modals (and the chat) size their backdrop to window.visualViewport, so they stay fully above the software keyboard (dvh alone left the sheet partly behind it). - On the owner's call, every profile / new-game picker is a native ` (the iOS wheel with 10-minute steps; the timezone - stays a native offset ``** (the away window as hour + 10-minute selects, the + timezone as a UTC-offset select): native time/wheel inputs render differently per + OS and can't be forced to match, and a select also avoids the iOS "clear" button + that would empty a time field. ## Deferred TODOs (cross-stage) @@ -639,3 +642,9 @@ Open details: deployment target/host; dashboards; load expectations. exists (Stage 9), wrap a code in a deep link and render it as a QR so a friend can add you by scanning rather than typing. The code semantics (12 h TTL, single use, one active per issuer) stay as-is; only the delivery changes. +- **TODO-6 β€” smart default for the friend-game "game type" (owner's idea, Stage 8).** + The play-with-friends form has no preselected variant today (an empty, required + pick). Default it from the player's history (the variant they play most, from + `account_stats` or a games query), falling back to their interface language + (en β†’ English, ru β†’ Russian/Π­Ρ€ΡƒΠ΄ΠΈΡ‚). Until then the explicit pick avoids guessing + wrong. diff --git a/ui/src/components/Modal.svelte b/ui/src/components/Modal.svelte index 7449b5e..acd189d 100644 --- a/ui/src/components/Modal.svelte +++ b/ui/src/components/Modal.svelte @@ -6,11 +6,38 @@ onclose, children, }: { title?: string; onclose?: () => void; children?: Snippet } = $props(); + + // Track the visual viewport so the backdrop covers only the area above an open + // mobile keyboard: dvh alone shrinks the sheet but the fixed, layout-viewport + // backdrop still centres it behind the keyboard. Sizing the backdrop to + // visualViewport keeps the sheet (and the start of a chat) fully on screen. + let vh = $state(0); + let top = $state(0); + $effect(() => { + const vv = typeof window !== 'undefined' ? window.visualViewport : null; + if (!vv) return; + const update = () => { + vh = vv.height; + top = vv.offsetTop; + }; + update(); + vv.addEventListener('resize', update); + vv.addEventListener('scroll', update); + return () => { + vv.removeEventListener('resize', update); + vv.removeEventListener('scroll', update); + }; + }); -
onclose?.()}> +
onclose?.()} +>