import React from 'react'; import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { ThemeProvider } from "@/components/ThemeProvider"; import { TVProvider } from "@/lib/contexts/TVContext"; import { TVNavigationInitializer } from "@/components/TVNavigationInitializer"; import { Analytics } from "@vercel/analytics/react"; import { ServiceWorkerRegister } from "@/components/ServiceWorkerRegister"; import { PasswordGate } from "@/components/PasswordGate"; import { siteConfig } from "@/lib/config/site-config"; import { AdKeywordsInjector } from "@/components/AdKeywordsInjector"; import { BackToTop } from "@/components/ui/BackToTop"; import { ScrollPositionManager } from "@/components/ScrollPositionManager"; import fs from 'fs'; import path from 'path'; // Server Component specifically for reading env/file (async for best practices) async function AdKeywordsWrapper() { let keywords: string[] = []; try { // 1. Try reading from file (Docker runtime support) const keywordsFile = process.env.AD_KEYWORDS_FILE; if (keywordsFile) { // Resolve absolute path or relative to CWD const filePath = path.isAbsolute(keywordsFile) ? keywordsFile : path.join(process.cwd(), keywordsFile); try { const content = await fs.promises.readFile(filePath, 'utf-8'); keywords = content.split(/[\n,]/).map((k: string) => k.trim()).filter((k: string) => k); console.log(`[AdFilter] Loaded ${keywords.length} keywords from file: ${filePath}`); } catch (fileError: unknown) { // Handle file not found (ENOENT) gracefully if ((fileError as NodeJS.ErrnoException).code !== 'ENOENT') { console.warn('[AdFilter] Error reading keywords file:', fileError); } } } // 2. Fallback to Env var (Runtime or Build time) if (keywords.length === 0) { const envKeywords = process.env.AD_KEYWORDS || process.env.NEXT_PUBLIC_AD_KEYWORDS; if (envKeywords) { keywords = envKeywords.split(/[\n,]/).map((k: string) => k.trim()).filter((k: string) => k); } } } catch (error) { console.warn('[AdFilter] Failed to load keywords:', error); } return ; } const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"], }); const geistMono = Geist_Mono({ variable: "--font-geist-mono", subsets: ["latin"], }); export const metadata: Metadata = { title: siteConfig.title, description: siteConfig.description, icons: { icon: '/icon.png', }, }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {/* PWA Manifest */} {/* Apple PWA Support */} {/* Theme Color (for browser address bar) */} {/* Mobile viewport */} {children} {/* ARIA Live Region for Screen Reader Announcements */}
{/* Google Cast SDK */}