import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react' import { View, Text, StyleSheet, ScrollView, Dimensions, Pressable, StatusBar as RNStatusBar, Platform, KeyboardAvoidingView, } from 'react-native' import { StatusBar } from 'expo-status-bar' import { SafeAreaView } from 'react-native-safe-area-context' import { Image } from 'expo-image' import { useRouter, useLocalSearchParams } from 'expo-router' import { useTranslation } from 'react-i18next' import { LeftArrowIcon, WhitePointsIcon } from '@/components/icon' import UploadReferenceImageDrawer from '@/components/drawer/UploadReferenceImageDrawer' import { StartGeneratingNotification } from '@/components/ui' import { DynamicForm, type DynamicFormRef, type FormSchema } from '@/components/DynamicForm' import { useTemplateActions } from '@/hooks/use-template-actions' import { useTemplateDetail } from '@/hooks/use-template-detail' import Toast from '@/components/ui/Toast' const { height: screenHeight } = Dimensions.get('window') export default function GenerateVideoScreen() { const { t } = useTranslation() const router = useRouter() const params = useLocalSearchParams() const { runTemplate, loading } = useTemplateActions() const { data: templateDetail, loading: templateLoading, execute: fetchTemplate } = useTemplateDetail() const [drawerVisible, setDrawerVisible] = useState(false) const [showNotification, setShowNotification] = useState(false) const [currentNodeId, setCurrentNodeId] = useState(null) const dynamicFormRef = useRef(null) useEffect(() => { if (params.templateId && typeof params.templateId === 'string') { fetchTemplate({ id: params.templateId }) } }, [params.templateId, fetchTemplate]) const formSchema = useMemo(() => ({ startNodes: templateDetail?.formSchema?.startNodes || [] }), [templateDetail]) const handleOpenDrawer = useCallback((nodeId: string) => { setCurrentNodeId(nodeId) setDrawerVisible(true) }, []) const handleSelectImage = useCallback(async (imageUri: string, mimeType?: string, fileName?: string) => { if (!currentNodeId) return if (dynamicFormRef.current) { dynamicFormRef.current.updateFieldValue(currentNodeId, imageUri, imageUri) } setDrawerVisible(false) setCurrentNodeId(null) }, [currentNodeId]) const handleFormSubmit = useCallback(async (data: Record) => { if (!templateDetail) return { error: { message: 'Template not found' } } const result = await runTemplate({ templateId: templateDetail.id, data, }) if (result.generationId) { setShowNotification(true) setTimeout(() => { setShowNotification(false) router.back() }, 3000) } return result }, [templateDetail, runTemplate, router]) return ( {Platform.OS === 'android' && ( )} {/* 顶部导航栏 */} router.back()} > {/* 主要内容区域 */} {/* 模板预览卡片 */} {templateDetail?.title} {templateDetail?.description} {/* 价格标签 */} {templateDetail?.price || 10} {/* 动态表单 */} {templateLoading ? ( {t('generateVideo.loading') || '加载中...'} ) : formSchema.startNodes && formSchema.startNodes.length > 0 ? ( ) : ( {t('generateVideo.noFormFields') || '暂无可填写的表单项'} )} {/* 图片上传抽屉 */} { setDrawerVisible(false) setCurrentNodeId(null) }} onSelectImage={handleSelectImage} /> {/* 通知组件 */} {showNotification && ( setShowNotification(false)} style={styles.notification} /> )} ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#090A0B', }, keyboardAvoidingView: { flex: 1, }, scrollView: { flex: 1, backgroundColor: '#090A0B', }, scrollContent: { flexGrow: 1, backgroundColor: '#090A0B', }, header: { flexDirection: 'row', alignItems: 'center', paddingTop: Platform.select({ ios: 17, android: 12, default: 17, }), paddingHorizontal: 12, paddingBottom: 20, }, backButton: { width: 22, height: 22, alignItems: 'center', justifyContent: 'center', }, content: { paddingHorizontal: 12, paddingTop: 16, backgroundColor: '#1C1E20', borderTopLeftRadius: 20, borderTopRightRadius: 20, gap: 16, minHeight: Platform.select({ ios: screenHeight - 100, android: screenHeight - 100, default: screenHeight - 60, }), }, // 模板预览卡片样式 templatePreviewCard: { backgroundColor: '#262A31', borderRadius: 16, padding: 12, borderWidth: 1, borderColor: '#2F3134', }, templateThumbnailContainer: { flexDirection: 'row', gap: 12, alignItems: 'center', }, templateThumbnail: { width: 80, height: 80, borderRadius: 12, backgroundColor: '#1C1E20', }, templateInfo: { flex: 1, gap: 4, }, templateTitle: { color: '#F5F5F5', fontSize: 16, fontWeight: '600', lineHeight: 22, }, templateDescription: { color: '#ABABAB', fontSize: 13, lineHeight: 18, }, priceTag: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end', gap: 6, marginTop: 8, paddingTop: 8, borderTopWidth: 1, borderTopColor: '#2F3134', }, priceText: { color: '#FFCF00', fontSize: 16, fontWeight: '600', }, // 表单容器样式 formContainer: { gap: 12, }, loadingContainer: { alignItems: 'center', justifyContent: 'center', padding: 40, }, loadingText: { color: '#8A8A8A', fontSize: 14, }, emptyContainer: { alignItems: 'center', justifyContent: 'center', padding: 40, backgroundColor: '#262A31', borderRadius: 12, }, emptyText: { color: '#8A8A8A', fontSize: 14, textAlign: 'center', }, // 通知容器样式 notificationContainer: { position: 'absolute', top: Platform.select({ ios: 60, android: 50, default: 60, }), left: 0, right: 0, paddingHorizontal: 8, zIndex: 1000, }, notification: { width: '100%', }, })