import React, { useEffect, useState } from 'react' import { View, Text, StyleSheet, Dimensions, Pressable, StatusBar as RNStatusBar, Alert, ScrollView, } 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 { LinearGradient } from 'expo-linear-gradient' import { LeftArrowIcon, DeleteIcon, EditIcon, ChangeIcon, WhiteStarIcon } from '@/components/icon' import { DeleteConfirmDialog } from '@/components/ui/delete-confirm-dialog' import LoadingState from '@/components/LoadingState' import ErrorState from '@/components/ErrorState' import { VideoPlayer } from '@/components/ui/video' import { useGenerationDetail, useDeleteGeneration, useRerunGeneration, useDownloadMedia, } from '@/hooks' const { width: screenWidth } = Dimensions.get('window') export default function GenerationRecordScreen() { const { t } = useTranslation() const router = useRouter() const params = useLocalSearchParams() const generationId = params.id as string const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) const { data: generation, loading, error, execute } = useGenerationDetail() const { deleteGeneration, loading: deleting } = useDeleteGeneration() const { rerun, loading: rerunning } = useRerunGeneration() const { download, loading: downloading, progress } = useDownloadMedia() useEffect(() => { if (generationId) { execute({ id: generationId }) } }, [generationId, execute]) const handleDelete = async () => { if (!generation) return const { error } = await deleteGeneration(generation.id) if (error) { Alert.alert(t('common.error'), error.message || t('generationRecord.deleteError')) } else { Alert.alert(t('common.success'), t('generationRecord.deleteSuccess')) router.back() } setDeleteDialogOpen(false) } const handleRerun = async () => { if (!generation) return const { generationId: newGenerationId, error } = await rerun(generation.id) if (error) { Alert.alert(t('common.error'), error.message || t('generationRecord.rerunError')) } else if (newGenerationId) { Alert.alert(t('common.success'), t('generationRecord.rerunSuccess')) // 跳转到新的生成记录详情页 router.replace({ pathname: '/generationRecord', params: { id: newGenerationId }, }) } } const handleTryAgain = () => { if (!generation?.template) return router.push({ pathname: '/generateVideo' as any, params: { templateId: generation.template.id }, }) } const handleDownload = async () => { if (!generation?.resultUrl?.[0]) return const url = generation.resultUrl[0] const mediaType = generation.type === 'VIDEO' ? 'video' : 'image' const { success, error } = await download(url, mediaType) if (success) { Alert.alert(t('common.success'), t('generationRecord.downloadSuccess')) } else { const errorMessage = error === 'Permission denied' ? t('generationRecord.permissionDenied') : t('generationRecord.downloadError') Alert.alert(t('common.error'), errorMessage) } } const getStatusText = (status: string) => { switch (status?.toLowerCase()) { case 'completed': case 'success': return t('generationRecord.statusCompleted') case 'pending': case 'processing': return t('generationRecord.statusPending') case 'failed': case 'error': return t('generationRecord.statusFailed') default: return status } } const getStatusColor = (status: string) => { switch (status?.toLowerCase()) { case 'completed': case 'success': return '#4ADE80' case 'pending': case 'processing': return '#FF9966' case 'failed': case 'error': return '#FF6B6B' default: return '#8A8A8A' } } const formatDate = (date: Date | string) => { const d = new Date(date) return d.toLocaleString() } if (!generationId) { return ( router.back()}> {t('generationRecord.title')} ) } if (loading) { return ( router.back()}> {t('generationRecord.title')} ) } if (error || !generation) { return ( router.back()}> {t('generationRecord.title')} execute({ id: generationId })} /> ) } const hasResult = generation.resultUrl && generation.resultUrl.length > 0 const isVideo = generation.type === 'VIDEO' const resultUrl = generation.resultUrl?.[0] return ( router.back()}> {t('generationRecord.title')} {/* 模板信息 */} {generation.template?.title || t('generationRecord.aiVideo')} {/* 生成结果预览 */} {t('generationRecord.generationResult')} {hasResult ? ( {isVideo ? ( ) : ( )} ) : ( {t('generationRecord.noResult')} )} {/* 状态信息 */} {t('generationRecord.status')} {getStatusText(generation.status)} {t('generationRecord.createdAt')} {formatDate(generation.createdAt)} {/* 操作按钮 */} {/* 下载按钮 - 主要操作使用渐变色 */} {hasResult && ( {downloading ? `${t('generationRecord.downloading')} ${Math.round(progress * 100)}%` : t('generationRecord.download')} )} {/* 次要操作按钮行 */} {/* 重新生成按钮 */} {t('generationRecord.regenerate')} {/* 再来一次按钮 */} {generation.template && ( {t('generationRecord.reEdit')} )} {/* 删除按钮 */} setDeleteDialogOpen(true)} disabled={deleting} > ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#090A0B', }, scrollContent: { paddingBottom: 40, }, header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingTop: 16, paddingBottom: 20, }, backButton: { width: 22, height: 22, alignItems: 'center', justifyContent: 'center', }, headerTitle: { color: '#F5F5F5', fontSize: 14, fontWeight: '600', flex: 1, textAlign: 'center', }, headerSpacer: { width: 22, }, templateSection: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, marginBottom: 16, gap: 8, }, categoryIcon: { width: 20, height: 20, alignItems: 'center', justifyContent: 'center', }, categoryText: { color: '#F5F5F5', fontSize: 16, fontWeight: '600', }, resultSection: { paddingHorizontal: 12, marginBottom: 20, }, sectionTitle: { color: '#8A8A8A', fontSize: 13, marginBottom: 12, paddingHorizontal: 4, }, mediaContainer: { width: screenWidth - 24, height: (screenWidth - 24) * 1.32, borderRadius: 16, overflow: 'hidden', backgroundColor: '#1C1E22', }, resultImage: { width: '100%', height: '100%', }, noResultContainer: { width: screenWidth - 24, height: 200, borderRadius: 16, backgroundColor: '#1C1E22', alignItems: 'center', justifyContent: 'center', }, noResultText: { color: '#8A8A8A', fontSize: 14, }, infoSection: { paddingHorizontal: 16, marginBottom: 24, gap: 12, }, infoRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, infoLabel: { color: '#8A8A8A', fontSize: 14, }, infoValue: { color: '#F5F5F5', fontSize: 14, fontWeight: '500', }, actionSection: { paddingHorizontal: 12, gap: 12, }, // 主要按钮 - 渐变色 primaryButtonContainer: { height: 48, borderRadius: 12, overflow: 'hidden', }, gradientButton: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', borderRadius: 12, }, primaryButtonText: { color: '#FFFFFF', fontSize: 16, fontWeight: '600', }, // 次要按钮行 secondaryButtonRow: { flexDirection: 'row', gap: 8, }, secondaryButton: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: 48, borderRadius: 12, backgroundColor: '#262A31', gap: 6, }, secondaryButtonText: { color: '#F5F5F5', fontSize: 14, fontWeight: '500', }, deleteButton: { width: 48, height: 48, borderRadius: 12, backgroundColor: '#262A31', alignItems: 'center', justifyContent: 'center', }, buttonDisabled: { opacity: 0.5, }, })