forked from 77media/video-flow
113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
'use client'
|
|
import './globals.css';
|
|
import '@/iconfont/iconfont.css';
|
|
import { createContext, useContext, useEffect, useState } from 'react';
|
|
import { Providers } from '@/components/providers';
|
|
import { ConfigProvider, theme } from 'antd';
|
|
import CallbackModal from '@/components/common/CallbackModal';
|
|
import { useAppStartupAnalytics } from '@/hooks/useAppStartupAnalytics';
|
|
import { gaEnabled, gaMeasurementId } from '@/lib/env';
|
|
|
|
// 创建上下文来传递弹窗控制方法
|
|
const CallbackModalContext = createContext<{
|
|
setShowCallbackModal: (show: boolean) => void
|
|
} | null>(null)
|
|
|
|
// Hook 来使用弹窗控制方法
|
|
export const useCallbackModal = () => {
|
|
const context = useContext(CallbackModalContext)
|
|
if (!context) {
|
|
throw new Error('useCallbackModal must be used within CallbackModalProvider')
|
|
}
|
|
return context
|
|
}
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const [showCallbackModal, setShowCallbackModal] = useState(false)
|
|
const [paymentType, setPaymentType] = useState<'subscription' | 'token'>('subscription')
|
|
|
|
// 应用启动时设置用户GA属性
|
|
useAppStartupAnalytics();
|
|
|
|
const openCallback = async function (ev: MessageEvent<any>) {
|
|
if (ev.data.type === 'waiting-payment') {
|
|
setPaymentType(ev.data.paymentType || 'subscription')
|
|
setShowCallbackModal(true)
|
|
}
|
|
}
|
|
useEffect(() => {
|
|
window.addEventListener('message', openCallback)
|
|
return () => {
|
|
window.removeEventListener('message', openCallback)
|
|
}
|
|
}, [])
|
|
return (
|
|
<html lang="en" suppressHydrationWarning>
|
|
<head>
|
|
<title>MovieFlow - AI Movie Studio</title>
|
|
<meta name="description" content="Share your story, or just a few words, and our AI turns it into a great film. We remove the barriers to creation. At MovieFlow, everyone is a movie master." />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
<link rel="icon" type="image/x-icon" sizes="16x16" href="/favicon.ico?v=1" />
|
|
<link rel="icon" type="image/x-icon" sizes="32x32" href="/favicon.ico?v=1" />
|
|
<link rel="canonical" href="https://movieflow.ai" />
|
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=1" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon.ico?v=1" />
|
|
{gaEnabled && (
|
|
<>
|
|
<script async src={`https://www.googletagmanager.com/gtag/js?id=${gaMeasurementId}`}></script>
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){window.dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('config', '${gaMeasurementId}', {
|
|
page_title: document.title,
|
|
page_location: window.location.href,
|
|
send_page_view: true
|
|
});
|
|
`,
|
|
}}
|
|
/>
|
|
</>
|
|
)}
|
|
</head>
|
|
<body className="font-sans antialiased">
|
|
<ConfigProvider
|
|
theme={{
|
|
algorithm: theme.darkAlgorithm,
|
|
token: {
|
|
// 自定义暗色主题颜色
|
|
colorBgContainer: '#1B1B1B',
|
|
colorBgElevated: '#1B1B1B',
|
|
colorBgMask: 'rgba(0, 0, 0, 0.6)',
|
|
borderRadius: 16,
|
|
},
|
|
components: {
|
|
Message: {
|
|
colorBgElevated: '#1f1f1f', // 自定义消息背景色
|
|
colorText: '#ffffff', // 自定义文字颜色
|
|
borderRadius: 8, // 自定义圆角
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<CallbackModalContext.Provider value={{ setShowCallbackModal }}>
|
|
<Providers>
|
|
{/* <ScreenAdapter /> */}
|
|
<div id="app" className='h-full w-full'>
|
|
{children}
|
|
{showCallbackModal && <CallbackModal paymentType={paymentType} onClose={() => setShowCallbackModal(false)} />}
|
|
</div>
|
|
</Providers>
|
|
</CallbackModalContext.Provider>
|
|
</ConfigProvider>
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|