@@ -3,19 +3,21 @@ import type { Metadata } from "next";
33import "./globals.css" ;
44import { ThemeProvider } from "@/components/ThemeProvider" ;
55import { AutoSync } from '@/components/AutoSync' ; // <-- 引入了自动同步组件
6+ import { SiteIconProvider } from '@/components/SiteIconProvider' ;
67import { TVProvider } from "@/lib/contexts/TVContext" ;
78import { TVNavigationInitializer } from "@/components/TVNavigationInitializer" ;
89import { Analytics } from "@vercel/analytics/react" ;
910import { ServiceWorkerRegister } from "@/components/ServiceWorkerRegister" ;
1011import { PasswordGate } from "@/components/PasswordGate" ;
11- import { siteConfig , SITE_ICON_PATH } from "@/lib/config/site-config" ;
12+ import { siteConfig } from "@/lib/config/site-config" ;
1213import { AdKeywordsInjector } from "@/components/AdKeywordsInjector" ;
1314import { BackToTop } from "@/components/ui/BackToTop" ;
1415import { ScrollPositionManager } from "@/components/ScrollPositionManager" ;
1516import { LocaleProvider } from "@/components/LocaleProvider" ;
1617import { RuntimeFeaturesProvider } from "@/components/RuntimeFeaturesProvider" ;
1718import { VideoTogetherController } from '@/components/VideoTogetherController' ;
1819import { getRuntimeFeatures } from "@/lib/server/runtime-features" ;
20+ import { resolveSiteIconSrc } from '@/lib/server/site-icon' ;
1921import fs from 'fs' ;
2022import path from 'path' ;
2123
@@ -61,19 +63,24 @@ async function AdKeywordsWrapper() {
6163 return < AdKeywordsInjector keywords = { keywords } /> ;
6264}
6365
64- export const metadata : Metadata = {
65- title : siteConfig . title ,
66- description : siteConfig . description ,
67- icons : {
68- icon : SITE_ICON_PATH ,
69- } ,
70- } ;
66+ export async function generateMetadata ( ) : Promise < Metadata > {
67+ const siteIconSrc = await resolveSiteIconSrc ( ) ;
7168
72- export default function RootLayout ( {
69+ return {
70+ title : siteConfig . title ,
71+ description : siteConfig . description ,
72+ icons : {
73+ icon : siteIconSrc ,
74+ } ,
75+ } ;
76+ }
77+
78+ export default async function RootLayout ( {
7379 children,
7480} : Readonly < {
7581 children : React . ReactNode ;
7682} > ) {
83+ const siteIconSrc = await resolveSiteIconSrc ( ) ;
7784 const runtimeFeatures = getRuntimeFeatures ( ) ;
7885 const videoTogetherScriptUrl =
7986 process . env . VIDEOTOGETHER_SCRIPT_URL ?. trim ( ) || DEFAULT_VIDEOTOGETHER_SCRIPT_URL ;
@@ -89,7 +96,7 @@ export default function RootLayout({
8996 < meta name = "apple-mobile-web-app-capable" content = "yes" />
9097 < meta name = "apple-mobile-web-app-status-bar-style" content = "black-translucent" />
9198 < meta name = "apple-mobile-web-app-title" content = "KVideo" />
92- < link rel = "apple-touch-icon" href = { SITE_ICON_PATH } />
99+ < link rel = "apple-touch-icon" href = { siteIconSrc } />
93100 { /* Theme Color (for browser address bar) */ }
94101 < meta name = "theme-color" content = "#000000" />
95102 { /* Mobile viewport */ }
@@ -99,30 +106,32 @@ export default function RootLayout({
99106 className = "antialiased"
100107 suppressHydrationWarning
101108 >
102- < ThemeProvider >
103- < RuntimeFeaturesProvider initialFeatures = { runtimeFeatures } >
104- < VideoTogetherController
105- envEnabled = { videoTogetherEnvEnabled }
106- scriptUrl = { videoTogetherScriptUrl }
107- settingUrl = { videoTogetherSettingUrl }
108- />
109- { /* 加入自动同步组件,它会在后台默默工作,我们放在 ThemeProvider 内部的最前面 */ }
110- < AutoSync />
111- < LocaleProvider />
109+ < SiteIconProvider iconSrc = { siteIconSrc } >
110+ < ThemeProvider >
111+ < RuntimeFeaturesProvider initialFeatures = { runtimeFeatures } >
112+ < VideoTogetherController
113+ envEnabled = { videoTogetherEnvEnabled }
114+ scriptUrl = { videoTogetherScriptUrl }
115+ settingUrl = { videoTogetherSettingUrl }
116+ />
117+ { /* 加入自动同步组件,它会在后台默默工作,我们放在 ThemeProvider 内部的最前面 */ }
118+ < AutoSync />
119+ < LocaleProvider />
112120
113- < TVProvider >
114- < TVNavigationInitializer />
115- < PasswordGate hasAuth = { ! ! ( process . env . ADMIN_PASSWORD || process . env . ACCOUNTS || process . env . ACCESS_PASSWORD ) } >
116- < AdKeywordsWrapper />
117- { children }
118- < BackToTop />
119- < ScrollPositionManager />
120- </ PasswordGate >
121- </ TVProvider >
122- < Analytics />
123- < ServiceWorkerRegister />
124- </ RuntimeFeaturesProvider >
125- </ ThemeProvider >
121+ < TVProvider >
122+ < TVNavigationInitializer />
123+ < PasswordGate hasAuth = { ! ! ( process . env . ADMIN_PASSWORD || process . env . ACCOUNTS || process . env . ACCESS_PASSWORD ) } >
124+ < AdKeywordsWrapper />
125+ { children }
126+ < BackToTop />
127+ < ScrollPositionManager />
128+ </ PasswordGate >
129+ </ TVProvider >
130+ < Analytics />
131+ < ServiceWorkerRegister />
132+ </ RuntimeFeaturesProvider >
133+ </ ThemeProvider >
134+ </ SiteIconProvider >
126135
127136 { /* ARIA Live Region for Screen Reader Announcements */ }
128137 < div
0 commit comments