chatdesk-ui/chatdesk-ui/app/[locale]/layout.tsx

168 lines
4.9 KiB
TypeScript

import { Toaster } from "@/components/ui/sonner"
import { GlobalState } from "@/components/utility/global-state"
import { Providers } from "@/components/utility/providers"
import TranslationsProvider from "@/components/utility/translations-provider"
import initTranslations from "@/lib/i18n"
//import { Database } from "@/supabase/types"
import { getSupabaseServerClient } from "@/lib/supabase/server"
import { Metadata, Viewport } from "next"
import { Inter } from "next/font/google"
import { cookies } from "next/headers"
import { ReactNode } from "react"
import "./globals.css"
//import Script from "next/script"
import { Suspense } from "react"
import { RuntimeEnvProvider } from "@/components/utility/runtime-env-provider"
const inter = Inter({ subsets: ["latin"] })
const APP_NAME = "ChatDesk UI"
const APP_DEFAULT_TITLE = "ChatDesk UI"
const APP_TITLE_TEMPLATE = "%s - ChatDesk UI"
const APP_DESCRIPTION = "ChatDesk UI PWA!"
interface RootLayoutProps {
children: ReactNode
params: {
locale: string
}
}
// 新增的 `getValidSupabaseUrl` 函数,带有超时机制和错误处理
// async function getValidSupabaseUrl(): Promise<string> {
// let url = getRuntimeEnv("SUPABASE_URL");
// const timeout = Date.now() + 30000; // 设置最大等待时间为30秒
// while (!url || !url.includes(":")) { // 检查是否包含合法的 IP 和端口
// if (Date.now() > timeout) {
// throw new Error("获取有效的 Supabase URL 超时");
// }
// console.log("等待有效的 Supabase URL...");
// await new Promise(resolve => setTimeout(resolve, 1000)); // 每1秒检查一次
// url = getRuntimeEnv("SUPABASE_URL");
// }
// return url;
// }
export async function generateMetadata({
params: { locale }
}: {
params: { locale: string }
}): Promise<Metadata> {
const { t } = await initTranslations(locale, ["translation"])
const appName = t("meta.appName")
const defaultTitle = t("meta.defaultTitle")
const description = t("meta.description")
const titleTemplate = `%s - ${defaultTitle}`
return {
applicationName: appName,
title: {
default: defaultTitle,
template: titleTemplate
},
description,
manifest: "/manifest.json",
appleWebApp: {
capable: true,
statusBarStyle: "black",
title: defaultTitle
},
formatDetection: {
telephone: false
},
openGraph: {
type: "website",
siteName: appName,
title: {
default: defaultTitle,
template: titleTemplate
},
description
},
twitter: {
card: "summary",
title: {
default: defaultTitle,
template: titleTemplate
},
description
}
}
}
export const viewport: Viewport = {
themeColor: "#000000"
}
const i18nNamespaces = ["translation"]
export default async function RootLayout({
children,
params: { locale }
}: RootLayoutProps) {
const cookieStore = cookies()
// 遍历所有 cookies
for (const cookie of cookieStore.getAll()) {
console.log(`🍪 Cookie: ${cookie.name} = ${cookie.value}`);
}
// let supabaseUrl = "";
// try {
// // 等待直到获取到有效的 Supabase URL
// supabaseUrl = await getValidSupabaseUrl();
// //console.log("==========>获取到有效的 Supabase URL: ", supabaseUrl);
// } catch (error) {
// console.error("Supabase URL 获取失败:", error);
// return <div>Failed to fetch Supabase configuration, please try again later.</div>; // 出现错误时返回一个友好的提示
// }
const supabase = getSupabaseServerClient()
const { data, error } = await supabase.auth.getSession();
if (error) {
console.log("[layout.tsx]............Session Error: ", error);
} else {
console.log("[layout.tsx]............Session Data: ", data.session);
}
const { t, resources } = await initTranslations(locale, i18nNamespaces)
return (
<html lang="en" suppressHydrationWarning>
<head>
{/* <Script
src="/env.js"
strategy="beforeInteractive" // 确保在 React 启动之前加载
/> */}
<RuntimeEnvProvider /> {/* ✅ 注入 window.RUNTIME_ENV.SUPABASE_URL */}
</head>
<body className={inter.className}>
{/* <RuntimeEnvProvider> */}
<Providers attribute="class" defaultTheme="dark">
<TranslationsProvider
namespaces={i18nNamespaces}
locale={locale}
resources={resources}
>
<Toaster richColors position="top-center" duration={3000} />
<Suspense fallback={null}>
<div className="bg-background text-foreground flex h-dvh flex-col items-center overflow-x-auto">
{data.session ? <GlobalState>{children}</GlobalState> : children}
</div>
</Suspense>
</TranslationsProvider>
</Providers>
{/* </RuntimeEnvProvider> */}
</body>
</html>
)
}