- Updated theme resolution logic to utilize a shared inline script for consistent theme application across routes. - Introduced `AppShell` and `ReadyGate` components to manage app readiness and theme synchronization, improving user experience. - Enhanced `GlobalError` and `NotFound` pages with a unified full-screen layout for better accessibility and visual consistency. - Refactored CSS to implement safe area insets for sticky headers and content safety, ensuring proper layout on various devices. - Added unit tests for new functionality and improved existing tests for better coverage and reliability.
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
/**
|
|
* Application initialization: access-denied logic and deep link routing.
|
|
* Document lang/title are owned by TelegramProvider (all routes).
|
|
*/
|
|
|
|
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { useAppStore } from "@/store/app-store";
|
|
import { RETRY_DELAY_MS } from "@/lib/constants";
|
|
|
|
export interface UseAppInitParams {
|
|
/** Whether the user is allowed (localhost or has valid initData). */
|
|
isAllowed: boolean;
|
|
/** Telegram Mini App start_param (e.g. "duty" for current duty deep link). */
|
|
startParam: string | undefined;
|
|
}
|
|
|
|
/**
|
|
* Handles access denied when not allowed and routes to current duty view when opened via startParam=duty.
|
|
*/
|
|
export function useAppInit({ isAllowed, startParam }: UseAppInitParams): void {
|
|
const setAccessDenied = useAppStore((s) => s.setAccessDenied);
|
|
const setLoading = useAppStore((s) => s.setLoading);
|
|
const setCurrentView = useAppStore((s) => s.setCurrentView);
|
|
|
|
// When not allowed (no initData and not localhost), show access denied after delay.
|
|
useEffect(() => {
|
|
if (isAllowed) {
|
|
setAccessDenied(false);
|
|
return;
|
|
}
|
|
const id = setTimeout(() => {
|
|
setAccessDenied(true);
|
|
setLoading(false);
|
|
}, RETRY_DELAY_MS);
|
|
return () => clearTimeout(id);
|
|
}, [isAllowed, setAccessDenied, setLoading]);
|
|
|
|
// When opened via deep link startParam=duty, show current duty view first.
|
|
useEffect(() => {
|
|
if (startParam === "duty") setCurrentView("currentDuty");
|
|
}, [startParam, setCurrentView]);
|
|
}
|