Stage 17 (contour round 3): Telegram Mini Apps polish, board scroll, keyboard overlay
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 10s
CI / ui (pull_request) Successful in 27s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 54s

- Telegram (lib/telegram.ts): chrome colours (setHeaderColor/setBackgroundColor/setBottomBarColor) match Telegram's header/bg/bottom bar to the app; native BackButton on sub-screens (app chevron hidden in TG); HapticFeedback on tile place/commit/error; enableClosingConfirmation while a game is open; disableVerticalSwipes so swipe-to-minimise doesn't fight tile drag / board scroll
- #9 board-only vertical scroll: Screen 'column' mode lets the board area scroll while score/status/rack/tab bar stay fixed (zoom keeps its own scroll)
- #10 check-word dialog opens in Modal keyboard-overlay mode (top-anchored, keyboard overlays the empty area) — no resize/relayout jank; other modals stay keyboard-aware
- docs: UI_DESIGN Telegram integration + vertical fit/keyboard; PLAN round 2-3 follow-ups
This commit is contained in:
Ilia Denisov
2026-06-06 12:55:46 +02:00
parent 645a503532
commit f6bffd1f57
9 changed files with 204 additions and 18 deletions
+29 -1
View File
@@ -9,7 +9,16 @@ import { GatewayError } from './client';
import { navigate, router } from './router.svelte';
import { errorKey, localeFrom, setLocale, t, type Locale } from './i18n/index.svelte';
import { applyReduceMotion, applyTelegramTheme, applyTheme, type ThemePref } from './theme';
import { insideTelegram, onTelegramPath, telegramColorScheme, telegramLaunch, telegramOnEvent } from './telegram';
import {
insideTelegram,
onTelegramPath,
telegramColorScheme,
telegramDisableVerticalSwipes,
telegramHaptic,
telegramLaunch,
telegramOnEvent,
telegramSetChrome,
} from './telegram';
import { parseStartParam } from './deeplink';
import { clearSession, loadPrefs, loadSession, saveSession, savePrefs } from './session';
import { clearGameCache } from './gamecache';
@@ -93,6 +102,7 @@ export function showToast(text: string, kind: Toast['kind'] = 'info'): void {
/** handleError maps a GatewayError to a toast; an invalid session logs out. */
export function handleError(err: unknown): void {
telegramHaptic('error');
if (err instanceof GatewayError) {
if (err.code === 'session_invalid' || err.code === 'unauthenticated') {
void logout();
@@ -200,6 +210,20 @@ export async function applyLinkResult(r: LinkResult): Promise<void> {
app.profile = await gateway.profileGet();
}
/**
* syncTelegramChrome paints Telegram's header/background/bottom bar from the app's live
* theme tokens, so the surrounding chrome matches the UI. Called after the theme is applied.
*/
function syncTelegramChrome(): void {
if (typeof document === 'undefined') return;
const cs = getComputedStyle(document.documentElement);
telegramSetChrome(
cs.getPropertyValue('--bg-elev').trim(),
cs.getPropertyValue('--bg').trim(),
cs.getPropertyValue('--bg-elev').trim(),
);
}
export async function bootstrap(): Promise<void> {
const prefs = await loadPrefs();
app.theme = prefs.theme ?? 'auto';
@@ -232,6 +256,10 @@ export async function bootstrap(): Promise<void> {
// so the OS prefers-color-scheme (which leaks into the Telegram Desktop webview)
// cannot fight it. Falls back to the stored preference when the SDK omits it.
applyTheme(telegramColorScheme() ?? app.theme);
// Match Telegram's chrome to the app and stop its swipe-down-to-minimise from
// fighting tile drag / board scroll.
syncTelegramChrome();
telegramDisableVerticalSwipes();
try {
await adoptSession(await gateway.authTelegram(launch.initData));
await routeStartParam(launch.startParam);