Review fixes: swipe (capture-phase, enabled in TG), TG header aligns to the nav band, DnD zoom delay 1s->0.7s
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Successful in 32s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Successful in 32s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
- Edge-swipe back now listens at the window in the CAPTURE phase (the board's pointer handlers can't swallow it) and is no longer skipped inside Telegram (where the owner tests it). - TG-fullscreen header: expose the device safe-area top (--tg-safe-top) and centre the title + menu pair within Telegram's nav band ([safe-top, content-top]) below the notch, keeping the band's height — lining up with Telegram's own controls. - DnD auto-zoom-on-hover delay reduced 1000ms -> 700ms. (Client-IP: diagnosed as the owner's home-router SNAT — the host caddy already receives 192.168.0.1 with no XFF, so the real IP is lost upstream of our stack; correct in prod. No code change.)
This commit is contained in:
@@ -44,6 +44,9 @@
|
||||
/* Height Telegram's native nav overlays at the top in fullscreen; set from the SDK's
|
||||
content-safe-area inset (Stage 17), 0 elsewhere. */
|
||||
--tg-content-top: 0px;
|
||||
/* Telegram device safe-area top (the notch); TG's own nav controls sit between it and
|
||||
--tg-content-top, so the in-app header aligns to that band (Stage 17), 0 elsewhere. */
|
||||
--tg-safe-top: 0px;
|
||||
--font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
||||
"Noto Sans", "Liberation Sans", sans-serif;
|
||||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 6px 16px rgba(0, 0, 0, 0.06);
|
||||
|
||||
@@ -89,17 +89,18 @@
|
||||
transform: rotate(45deg);
|
||||
margin-left: 3px;
|
||||
}
|
||||
/* Telegram fullscreen: TG's native nav overlays a band of height --tg-content-top at the top
|
||||
of the viewport. Pull our title + menu up into the BOTTOM of that band and centre them as a
|
||||
pair (hamburger right of the title) so they line up with Telegram's own nav controls rather
|
||||
than floating above them (Stage 17). */
|
||||
/* Telegram fullscreen: TG's native nav occupies the band between the device notch
|
||||
(--tg-safe-top) and --tg-content-top. Our header spans that full band (so the layout below
|
||||
is unchanged) and centres the title + menu as a pair (hamburger right of the title) within
|
||||
it, BELOW the notch — lining them up vertically with Telegram's own back/menu controls,
|
||||
which sit in the band's corners (Stage 17). */
|
||||
:global(html.tg-fullscreen) .bar {
|
||||
min-height: var(--tg-content-top);
|
||||
box-sizing: border-box;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 0;
|
||||
padding-bottom: 6px;
|
||||
padding-top: var(--tg-safe-top);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
:global(html.tg-fullscreen) .spacer {
|
||||
display: none;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import Header from './Header.svelte';
|
||||
import AdBanner from './AdBanner.svelte';
|
||||
import { navigate } from '../lib/router.svelte';
|
||||
import { insideTelegram } from '../lib/telegram';
|
||||
|
||||
// The app-shell layout (all screens): the nav bar grows; the ad strip, content and
|
||||
// optional tab bar pin to the bottom (ad directly above the content). Pass `scroll`
|
||||
@@ -37,25 +36,28 @@
|
||||
const SHOW_AD_BANNER = false;
|
||||
|
||||
// Edge-swipe back (Stage 17): a left-edge rightward drag returns to `back`, the standard
|
||||
// mobile gesture. Armed only from the very left edge (<=24px) so it never competes with the
|
||||
// board's own horizontal gestures; touch/pen only. Skipped inside Telegram, whose native
|
||||
// back button + swipe already cover this (and would otherwise double up).
|
||||
function onEdgeDown(e: PointerEvent): void {
|
||||
if (!back || e.pointerType === 'mouse' || insideTelegram() || e.clientX > 24) return;
|
||||
const x0 = e.clientX;
|
||||
const y0 = e.clientY;
|
||||
const onUp = (ev: PointerEvent) => {
|
||||
window.removeEventListener('pointerup', onUp);
|
||||
const dx = ev.clientX - x0;
|
||||
const dy = ev.clientY - y0;
|
||||
if (back && dx > 64 && Math.abs(dx) > Math.abs(dy) * 1.4) navigate(back);
|
||||
};
|
||||
window.addEventListener('pointerup', onUp);
|
||||
}
|
||||
// mobile gesture. Listened at the window in the CAPTURE phase so the board's own pointer
|
||||
// handlers (which capture/stop the event) can never swallow it; armed only from the very
|
||||
// left edge (<=24px), touch/pen only, so it never competes with the board's gestures.
|
||||
$effect(() => {
|
||||
function onDown(e: PointerEvent) {
|
||||
if (!back || e.pointerType === 'mouse' || e.clientX > 24) return;
|
||||
const x0 = e.clientX;
|
||||
const y0 = e.clientY;
|
||||
const onUp = (ev: PointerEvent) => {
|
||||
window.removeEventListener('pointerup', onUp, true);
|
||||
const dx = ev.clientX - x0;
|
||||
const dy = ev.clientY - y0;
|
||||
if (back && dx > 64 && Math.abs(dx) > Math.abs(dy) * 1.4) navigate(back);
|
||||
};
|
||||
window.addEventListener('pointerup', onUp, true);
|
||||
}
|
||||
window.addEventListener('pointerdown', onDown, true);
|
||||
return () => window.removeEventListener('pointerdown', onDown, true);
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="screen" onpointerdown={onEdgeDown}>
|
||||
<div class="screen">
|
||||
<Header {title} {back} {menu} grow={growNav} />
|
||||
{#if SHOW_AD_BANNER}<AdBanner />{/if}
|
||||
<main class="content" class:scroll class:fill={!growNav} class:column>{@render children?.()}</main>
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
zoomed = true;
|
||||
telegramHaptic('light');
|
||||
}
|
||||
}, 1000)
|
||||
}, 700)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
onTelegramPath,
|
||||
telegramColorScheme,
|
||||
telegramContentSafeAreaTop,
|
||||
telegramSafeAreaTop,
|
||||
telegramDisableVerticalSwipes,
|
||||
telegramHaptic,
|
||||
telegramLaunch,
|
||||
@@ -238,6 +239,7 @@ function syncTelegramSafeArea(): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
const top = telegramContentSafeAreaTop();
|
||||
document.documentElement.style.setProperty('--tg-content-top', `${top}px`);
|
||||
document.documentElement.style.setProperty('--tg-safe-top', `${telegramSafeAreaTop()}px`);
|
||||
document.documentElement.classList.toggle('tg-fullscreen', top > 0);
|
||||
}
|
||||
|
||||
@@ -279,6 +281,7 @@ export async function bootstrap(): Promise<void> {
|
||||
syncTelegramChrome();
|
||||
syncTelegramSafeArea();
|
||||
telegramOnEvent('contentSafeAreaChanged', syncTelegramSafeArea);
|
||||
telegramOnEvent('safeAreaChanged', syncTelegramSafeArea);
|
||||
telegramOnEvent('fullscreenChanged', syncTelegramSafeArea);
|
||||
telegramDisableVerticalSwipes();
|
||||
try {
|
||||
|
||||
@@ -11,6 +11,7 @@ interface TelegramWebApp {
|
||||
themeParams?: TelegramThemeParams;
|
||||
colorScheme?: 'light' | 'dark';
|
||||
isFullscreen?: boolean;
|
||||
safeAreaInset?: { top: number; bottom: number; left: number; right: number };
|
||||
contentSafeAreaInset?: { top: number; bottom: number; left: number; right: number };
|
||||
ready?: () => void;
|
||||
expand?: () => void;
|
||||
@@ -110,6 +111,16 @@ export function telegramContentSafeAreaTop(): number {
|
||||
return webApp()?.contentSafeAreaInset?.top ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* telegramSafeAreaTop returns the device safe-area top inset (px) — the notch / status bar
|
||||
* (Bot API 8.0). Telegram's own nav controls sit in the band between it and
|
||||
* telegramContentSafeAreaTop, so aligning our header to that band lines it up with them. 0
|
||||
* outside Telegram or on older clients.
|
||||
*/
|
||||
export function telegramSafeAreaTop(): number {
|
||||
return webApp()?.safeAreaInset?.top ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* telegramDisableVerticalSwipes turns off Telegram's swipe-down-to-minimise gesture so
|
||||
* it does not fight tile drag-and-drop or the board's vertical scroll.
|
||||
|
||||
Reference in New Issue
Block a user