feat(game): finished-game export as a PNG image behind a format chooser #159

Merged
developer merged 2 commits from feature/game-export-image into development 2026-07-02 15:29:41 +00:00
Owner

The 📤 export of a finished game now opens a format chooser — Telegram's native popup inside Telegram (image / GCG / cancel), the app's own modal elsewhere — offering the existing GCG file and a new client-rendered PNG of the final position.

The image (ui/src/lib/gameimage.ts, Canvas 2D, lazy dynamic import, zero new dependencies): always the light palette, classic A..O / 1..15 axes, premium squares as plain fills (no text labels), in-game tile styling, no last-move highlight; per-seat scoresheet with GCG-convention coordinates (across = row-first 8G, down = column-first H8), multi-word plays on a smaller second line, localized pass/exchange/resign/timeout notes, the endgame rack-settlement ± row, 🏆 by the winner, and a hostname · finish date footer (device locale). Fixed scoresheet typography — a long game stretches the board instead (never below its minimum).

Delivery: Web Share (cancelled share = no-op, never a blob fallback) or a desktop download; Android Telegram/VK WebViews and the desktop VK iframe — where a binary PNG has neither Web Share, a working <a download>, nor a clipboard-text fallback — get a preview modal (data: URL image + long-press/right-click save hint + copy-image where ClipboardItem exists). On-device verification of exactly those webviews is on the contour after merge.

Owner signed off the rendered samples (3 iterations: value-digit padding, label-free premiums, multi-word rows).

Tests: vitest (scoresheet/layout/notation/delivery picker) + Playwright e2e (chooser download paths on both engines, native-TG popup → preview modal). Docs baked: FUNCTIONAL(+_ru), UI_DESIGN.

The 📤 export of a finished game now opens a format chooser — Telegram's native popup inside Telegram (image / GCG / cancel), the app's own modal elsewhere — offering the existing GCG file and a new client-rendered PNG of the final position. **The image** (`ui/src/lib/gameimage.ts`, Canvas 2D, lazy dynamic import, zero new dependencies): always the light palette, classic A..O / 1..15 axes, premium squares as plain fills (no text labels), in-game tile styling, no last-move highlight; per-seat scoresheet with GCG-convention coordinates (across = row-first `8G`, down = column-first `H8`), multi-word plays on a smaller second line, localized pass/exchange/resign/timeout notes, the endgame rack-settlement ± row, 🏆 by the winner, and a `hostname · finish date` footer (device locale). Fixed scoresheet typography — a long game stretches the board instead (never below its minimum). **Delivery:** Web Share (cancelled share = no-op, never a blob fallback) or a desktop download; Android Telegram/VK WebViews and the desktop VK iframe — where a binary PNG has neither Web Share, a working `<a download>`, nor a clipboard-text fallback — get a preview modal (data: URL image + long-press/right-click save hint + copy-image where `ClipboardItem` exists). On-device verification of exactly those webviews is on the contour after merge. Owner signed off the rendered samples (3 iterations: value-digit padding, label-free premiums, multi-word rows). Tests: vitest (scoresheet/layout/notation/delivery picker) + Playwright e2e (chooser download paths on both engines, native-TG popup → preview modal). Docs baked: FUNCTIONAL(+_ru), UI_DESIGN.
developer added 1 commit 2026-07-02 14:20:52 +00:00
feat(game): finished-game export as a PNG image behind a format chooser
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 59s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m16s
a0eacf3011
The history header's export button now opens a chooser — Telegram's
native popup inside Telegram, the app's own modal elsewhere — offering
the GCG file and a new client-rendered PNG of the final position
(lib/gameimage, Canvas 2D, lazy dynamic import, zero dependencies):
light theme, classic A..O/1..15 axes, label-free premium fills, and a
fixed-typography per-seat scoresheet with GCG-style move coordinates,
multi-word sub-lines, endgame rack-settlement row, winner trophy and a
hostname + device-locale finish date footer; a long game stretches the
board, never the typography.

Delivery mirrors the GCG rules (Web Share with no blob fallback, else
download) except on Android Telegram/VK WebViews and the desktop VK
iframe, where a binary PNG has no clipboard-text fallback: those get a
preview modal with a long-press/right-click save hint and a copy-image
button where ClipboardItem exists.
developer added 1 commit 2026-07-02 15:16:07 +00:00
fix(game): own export chooser modal; PNG option outside in-app webviews only
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 59s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m26s
946420db93
Telegram's native showPopup delivers its callback with no user
activation, so navigator.share (TG iOS) and clipboard writes (TG
Android GCG copy) silently fail from it — the chooser is now always the
app's own modal, keeping the button click's gesture alive for the
delivery APIs.

The data:URL preview modal is dropped: the Android TG/VK long-press
menu mangles data: URLs (dead download, black-screen open, base64
clipboard garbage), so a binary PNG has no working client-side route in
those webviews at all. The image option is withheld there until the
server-rendered signed-URL delivery (Telegram downloadFile /
VKWebAppDownloadFile) lands; the plain web and mobile browsers keep it.

On-device findings by the owner on the test contour (TG iOS, TG
Android, VK Android).
owner approved these changes 2026-07-02 15:29:05 +00:00
Dismissed
owner approved these changes 2026-07-02 15:29:26 +00:00
developer merged commit 16a4431158 into development 2026-07-02 15:29:41 +00:00
developer deleted branch feature/game-export-image 2026-07-02 15:29:41 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#159