feat: enhance theme handling and layout components for Telegram Mini App
- 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.
This commit is contained in:
@@ -8,10 +8,8 @@
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useAppStore, type AppState } from "@/store/app-store";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
import { useTelegramTheme } from "@/hooks/use-telegram-theme";
|
||||
import { useTelegramAuth } from "@/hooks/use-telegram-auth";
|
||||
import { useAppInit } from "@/hooks/use-app-init";
|
||||
import { callMiniAppReadyOnce } from "@/lib/telegram-ready";
|
||||
import { fetchAdminMe } from "@/lib/api";
|
||||
import { getLang } from "@/i18n/messages";
|
||||
import { AccessDeniedScreen } from "@/components/states/AccessDeniedScreen";
|
||||
@@ -19,8 +17,6 @@ import { CurrentDutyView } from "@/components/current-duty/CurrentDutyView";
|
||||
import { CalendarPage } from "@/components/CalendarPage";
|
||||
|
||||
export default function Home() {
|
||||
useTelegramTheme();
|
||||
|
||||
const { initDataRaw, startParam, isLocalhost } = useTelegramAuth();
|
||||
const isAllowed = isLocalhost || !!initDataRaw;
|
||||
|
||||
@@ -35,7 +31,7 @@ export default function Home() {
|
||||
fetchAdminMe(initDataRaw, getLang()).then(({ is_admin }) => setIsAdmin(is_admin));
|
||||
}, [isAllowed, initDataRaw, setIsAdmin]);
|
||||
|
||||
const { accessDenied, currentView, setCurrentView, setSelectedDay, appContentReady } =
|
||||
const { accessDenied, currentView, setCurrentView, setSelectedDay, appContentReady, setAppContentReady } =
|
||||
useAppStore(
|
||||
useShallow((s: AppState) => ({
|
||||
accessDenied: s.accessDenied,
|
||||
@@ -43,15 +39,16 @@ export default function Home() {
|
||||
setCurrentView: s.setCurrentView,
|
||||
setSelectedDay: s.setSelectedDay,
|
||||
appContentReady: s.appContentReady,
|
||||
setAppContentReady: s.setAppContentReady,
|
||||
}))
|
||||
);
|
||||
|
||||
// When content is ready, tell Telegram to hide native loading and show our app.
|
||||
// When showing access-denied or current-duty view, mark content ready so ReadyGate can call miniAppReady().
|
||||
useEffect(() => {
|
||||
if (appContentReady) {
|
||||
callMiniAppReadyOnce();
|
||||
if (accessDenied || currentView === "currentDuty") {
|
||||
setAppContentReady(true);
|
||||
}
|
||||
}, [appContentReady]);
|
||||
}, [accessDenied, currentView, setAppContentReady]);
|
||||
|
||||
const handleBackFromCurrentDuty = useCallback(() => {
|
||||
setCurrentView("calendar");
|
||||
@@ -59,7 +56,9 @@ export default function Home() {
|
||||
}, [setCurrentView, setSelectedDay]);
|
||||
|
||||
const content = accessDenied ? (
|
||||
<AccessDeniedScreen primaryAction="reload" />
|
||||
<div className="content-safe mx-auto flex min-h-[var(--tg-viewport-stable-height,100vh)] w-full max-w-[var(--max-width-app)] flex-col bg-background px-3 pb-6">
|
||||
<AccessDeniedScreen primaryAction="reload" />
|
||||
</div>
|
||||
) : currentView === "currentDuty" ? (
|
||||
<div className="content-safe mx-auto flex min-h-[var(--tg-viewport-stable-height,100vh)] w-full max-w-[var(--max-width-app)] flex-col bg-background px-3 pb-6">
|
||||
<CurrentDutyView
|
||||
|
||||
Reference in New Issue
Block a user