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

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).
This commit is contained in:
Ilia Denisov
2026-07-02 17:16:05 +02:00
parent a0eacf3011
commit 946420db93
9 changed files with 95 additions and 202 deletions
+10 -8
View File
@@ -406,14 +406,16 @@ enabled on the first, uncached load) and flip in place when an event refreshes t
- **History / export**: the in-game slide-down history lays each move out in a per-seat grid
(the word(s) and the move score, no running total); the 📤 in the history header appears
only once the game is finished — never in an honest-AI game (throwaway practice) — and
opens a **format chooser**: Telegram's native popup inside Telegram (image / GCG / cancel),
the app's own modal elsewhere (the accent button leads with the image, the GCG file is the
quiet alternative; GCG needs the connection, the image renders locally). The GCG file goes
by Web Share where available, a clipboard copy in an Android in-app WebView (Telegram / VK,
which has neither Web Share nor a working download), else a Blob download. The image goes by
Web Share / Blob download too, but on those in-app WebViews (and the desktop VK iframe) it
opens a **preview modal** instead — the PNG as a data: URL with a long-press / right-click
save hint and a copy-image button where `ClipboardItem` exists. Confirming a resign reveals
opens the **format chooser**: always the app's own modal, never Telegram's native popup
(a `showPopup` callback carries no user activation, which silently breaks the
`navigator.share` / clipboard delivery it leads to — on-device finding). The accent button
leads with the image where offered, the GCG file is the quiet alternative (GCG needs the
connection, the image renders locally). The GCG file goes by Web Share where available, a
clipboard copy in an Android in-app WebView (Telegram / VK, which has neither Web Share nor
a working download), else a Blob download. The image option shows **only outside the in-app
WebViews** for now (a binary PNG has no working route there — no Web Share, a dead
`<a download>`, a text-only clipboard, and the long-press menu mangles data: URLs); it
returns there with the server-rendered signed-URL delivery. Confirming a resign reveals
the full board: it closes the history drawer (portrait) and zooms the board out.
- **Export image** (`lib/gameimage.ts`, Canvas 2D, dynamically imported): always the light
palette (pinned constants mirroring `app.css`), the final board with classic axes A..O /