- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability. - Updated the `.gitignore` to exclude Next.js build artifacts and node modules. - Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack. - Enhanced Dockerfile to support the new build process for the Next.js application. - Updated CI workflow to build and test the Next.js application. - Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking. - Refactored frontend testing setup to accommodate the new structure and testing framework. - Removed legacy webapp files and dependencies to streamline the project.
53 lines
3.2 KiB
TypeScript
53 lines
3.2 KiB
TypeScript
/**
|
|
* Next.js root error boundary. Replaces the root layout when an unhandled error occurs.
|
|
* Must define its own html/body. For most runtime errors the in-app AppErrorBoundary is used.
|
|
*/
|
|
|
|
"use client";
|
|
|
|
import "./globals.css";
|
|
import { getLang, translate } from "@/i18n/messages";
|
|
|
|
export default function GlobalError({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
const lang = getLang();
|
|
return (
|
|
<html
|
|
lang={lang === "ru" ? "ru" : "en"}
|
|
data-theme="dark"
|
|
suppressHydrationWarning
|
|
>
|
|
<head>
|
|
{/* Same theme detection as layout: hash / Telegram / prefers-color-scheme → data-theme */}
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `(function(){var scheme='dark';var root=document.documentElement;var hash=typeof location!=='undefined'&&location.hash?location.hash.slice(1):'';if(hash){var params={};hash.split('&').forEach(function(p){var i=p.indexOf('=');if(i===-1)return;var k=decodeURIComponent(p.slice(0,i));var v=p.slice(i+1);params[k]=v;});if(params.tgWebAppColorScheme==='light'||params.tgWebAppColorScheme==='dark')scheme=params.tgWebAppColorScheme;if(params.tgWebAppThemeParams){try{var theme=JSON.parse(decodeURIComponent(params.tgWebAppThemeParams));var tgKeys=['bg_color','text_color','hint_color','link_color','button_color','button_text_color','secondary_bg_color','header_bg_color','accent_text_color','destructive_text_color','section_bg_color','section_header_text_color','section_separator_color','subtitle_text_color','bottom_bar_bg_color'];tgKeys.forEach(function(k){var v=theme[k];if(v&&typeof v==='string')root.style.setProperty('--tg-theme-'+k.replace(/_/g,'-'),v);});Object.keys(theme).forEach(function(k){var v=theme[k];if(v&&typeof v==='string')root.style.setProperty('--tg-theme-'+k.replace(/_/g,'-'),v);});}catch(e){}}}var twa=typeof window!=='undefined'&&window.Telegram&&window.Telegram.WebApp;if(scheme!=='light'&&scheme!=='dark'&&twa&&(twa.colorScheme==='light'||twa.colorScheme==='dark'))scheme=twa.colorScheme;if(scheme!=='light'&&scheme!=='dark'){try{var s=getComputedStyle(root).getPropertyValue('--tg-color-scheme').trim();if(s==='light'||s==='dark')scheme=s;}catch(e){} }if(scheme!=='light'&&scheme!=='dark')scheme=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';root.setAttribute('data-theme',scheme);if(twa){if(twa.setBackgroundColor)twa.setBackgroundColor('bg_color');if(twa.setHeaderColor)twa.setHeaderColor('bg_color');}})();`,
|
|
}}
|
|
/>
|
|
</head>
|
|
<body className="antialiased">
|
|
<div className="flex min-h-screen flex-col items-center justify-center gap-4 bg-background px-4 text-foreground">
|
|
<h1 className="text-xl font-semibold">
|
|
{translate(lang, "error_boundary.message")}
|
|
</h1>
|
|
<p className="text-center text-muted-foreground">
|
|
{translate(lang, "error_boundary.description")}
|
|
</p>
|
|
<button
|
|
type="button"
|
|
onClick={() => reset()}
|
|
className="rounded-lg bg-primary px-4 py-2 text-primary-foreground hover:bg-primary/90"
|
|
>
|
|
{translate(lang, "error_boundary.reload")}
|
|
</button>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|