c32a15730a
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 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
The first attempt (the App.svelte `started` gate) targeted the first pane mount,
but the slide is a second render. On a Telegram cold launch the URL fragment is
Telegram's #tgWebAppData=... launch params, which the router parsed as notfound;
bootstrap's navigate('/') then corrected it to the lobby asynchronously, re-keying
the route pane (notfound -> lobby) and sliding the lobby in as if returning from a
screen. A reload was static because the hash was already #/.
Treat a Telegram launch fragment as the lobby root in the router, so the route is
correct from the first pane (no re-key, no slide). Extract the pure hash->Route
parsing into routeparse.ts so it unit-tests without a DOM, and revert the gate
(the first pane never slid — local transitions skip the initial mount, as clean
browser launches showed).
Tests: routeparse unit tests (incl. the tgWebApp fragment); an e2e that launches
with the fragment in the URL and asserts the lobby plus the normalised #/ hash.
29 lines
966 B
TypeScript
29 lines
966 B
TypeScript
// Minimal dependency-free hash router. Hash routing survives a reload and works on
|
|
// a file:// origin (Capacitor native packaging), where there is no server to honour
|
|
// deep paths. The route is a reactive rune so screens re-render on navigation. The pure
|
|
// hash->Route parsing lives in routeparse.ts (unit-tested without a DOM).
|
|
|
|
import { parse, type Route, type RouteName } from './routeparse';
|
|
|
|
export type { Route, RouteName };
|
|
|
|
export const router = $state<{ route: Route }>({
|
|
route: parse(typeof location !== 'undefined' ? location.hash : ''),
|
|
});
|
|
|
|
if (typeof window !== 'undefined') {
|
|
window.addEventListener('hashchange', () => {
|
|
router.route = parse(location.hash);
|
|
});
|
|
}
|
|
|
|
/** navigate switches the hash route (and forces a re-parse if it is unchanged). */
|
|
export function navigate(path: string): void {
|
|
const target = '#' + path;
|
|
if (location.hash === target) {
|
|
router.route = parse(target);
|
|
} else {
|
|
location.hash = path;
|
|
}
|
|
}
|