Apps, web, i18n, UI, partners, payouts, backoffice, bariki, prod infra
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
45d7512d2b
commit
3489e0b816
319 files changed
+45483
-121
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import { useEffect, useSyncExternalStore } from 'react';
|
||||
import { tg } from './telegram.ts';
|
||||
|
||||
/**
|
||||
* Минимальный hash-роутер: Mini App открывается по одному URL, а hash переживает
|
||||
* перезагрузку WebView и не требует настройки сервера.
|
||||
*/
|
||||
function subscribe(cb: () => void) {
|
||||
window.addEventListener('hashchange', cb);
|
||||
return () => window.removeEventListener('hashchange', cb);
|
||||
}
|
||||
// Telegram открывает Mini App с #tgWebAppData=… — это не маршрут, а параметры запуска
|
||||
const snapshot = () => {
|
||||
const h = window.location.hash.replace(/^#/, '');
|
||||
return h.startsWith('/') ? h : '/';
|
||||
};
|
||||
|
||||
export function useLocation() {
|
||||
const raw = useSyncExternalStore(subscribe, snapshot, () => '/');
|
||||
const [path, search = ''] = raw.split('?');
|
||||
return { path: path || '/', query: new URLSearchParams(search) };
|
||||
}
|
||||
|
||||
export function navigate(to: string, opts: { replace?: boolean } = {}) {
|
||||
if (opts.replace) window.location.replace(`#${to}`);
|
||||
else window.location.hash = to;
|
||||
}
|
||||
|
||||
/** Сопоставление '/orders/:id' → { id } */
|
||||
export function match(pattern: string, path: string): Record<string, string> | null {
|
||||
const p = pattern.split('/').filter(Boolean);
|
||||
const a = path.split('/').filter(Boolean);
|
||||
if (p.length !== a.length) return null;
|
||||
const params: Record<string, string> = {};
|
||||
for (let i = 0; i < p.length; i++) {
|
||||
if (p[i]!.startsWith(':')) params[p[i]!.slice(1)] = decodeURIComponent(a[i]!);
|
||||
else if (p[i] !== a[i]) return null;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/** Кнопка «Назад» Telegram на всех экранах, кроме корневых */
|
||||
export function useTelegramBack(path: string, roots: string[]) {
|
||||
useEffect(() => {
|
||||
const back = tg()?.BackButton;
|
||||
if (!back) return;
|
||||
const onBack = () => window.history.back();
|
||||
if (roots.includes(path)) back.hide();
|
||||
else {
|
||||
back.show();
|
||||
back.onClick(onBack);
|
||||
}
|
||||
return () => back.offClick(onBack);
|
||||
}, [path, roots]);
|
||||
}
|
||||
Reference in new issue
Block a user