Merge pull request 'fix(ui): copy GCG to clipboard on Android in-app WebViews' (#151) from feature/gcg-export-android-fix into development
CI / changes (push) Successful in 2s
CI / unit (push) Has been skipped
CI / integration (push) Has been skipped
CI / ui (push) Successful in 57s
CI / gate (push) Successful in 0s
CI / deploy (push) Successful in 1m13s

This commit was merged in pull request #151.
This commit is contained in:
2026-07-01 11:23:59 +00:00
10 changed files with 109 additions and 35 deletions
+18 -1
View File
@@ -21,6 +21,7 @@
import { alphabetLetters, hasAlphabet } from '../lib/alphabet';
import { hintsLeft } from '../lib/hints';
import { shareOrDownloadGcg } from '../lib/share';
import { insideVK, vkCopyText } from '../lib/vk';
import { getCachedGame, setCachedGame, setCachedDraft, type CachedGame } from '../lib/gamecache';
import { patchLobbyGame } from '../lib/lobbycache';
import { applyGameOver, applyMoveDelta, applyOpponentJoined, type DeltaResult } from '../lib/gamedelta';
@@ -838,12 +839,28 @@
async function exportGcg() {
try {
await shareOrDownloadGcg(await gateway.exportGcg(id));
const gcg = await gateway.exportGcg(id);
const outcome = await shareOrDownloadGcg(gcg, insideTelegram() || insideVK(), copyGcgText);
if (outcome === 'copied') showToast(t('game.gcgCopied'), 'info');
else if (outcome === 'failed') showToast(t('error.generic'), 'error');
} catch (e) {
handleError(e);
}
}
// The GCG export copies to the clipboard in an Android in-app WebView (no Web Share, a dead
// <a download>): VKWebAppCopyText inside VK — which also works in the desktop VK iframe, where
// navigator.clipboard is blocked — and navigator.clipboard elsewhere.
async function copyGcgText(text: string): Promise<boolean> {
if (insideVK()) return vkCopyText(text);
try {
await navigator.clipboard.writeText(text);
return true;
} catch {
return false;
}
}
// --- move history: open by tapping the score bar, close by tapping or swiping up the board ---
// The boardwrap surface drives two gestures, selected by `historyOpen`:
// - open: the slid board is inert (CSS pointer-events), so the whole board reads as a