import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Progress } from '@/components/ui/progress'; import { Textarea } from '@/components/ui/textarea'; import { Clock10Icon, Download, Droplets } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; import useUserStore from '@/stores/UserStore'; const VideoDownloadModal = ({ nonWatermarkVideosLeft = 0, isOpen, onClose, ffmpegCommand, handleDownloadButton, isExporting, exportProgress, exportStatus, }) => { const [showDebug, setShowDebug] = useState(false); const [isPremiumExport, setIsPremiumExport] = useState(false); const [estimatedTimeRemaining, setEstimatedTimeRemaining] = useState(null); const [status, setStatus] = useState('start'); // 'start', 'processing', 'complete' const exportStartTime = useRef(null); const lastProgressTime = useRef(null); const lastProgress = useRef(0); const { premiumExportRequest, premiumExportComplete } = useUserStore(); const handleExportWithoutWatermark = async () => { setIsPremiumExport(true); setEstimatedTimeRemaining(null); // Call premiumExportRequest and check response const response = await premiumExportRequest(); if (response?.error) { // Halt the process if there's an error setIsPremiumExport(false); return; } if (response?.success) { // Continue with export if successful setStatus('processing'); handleDownloadButton(); } }; const handleExportWithWatermark = () => { setIsPremiumExport(false); setEstimatedTimeRemaining(null); setStatus('processing'); handleDownloadButton(); }; const handleClose = async () => { onClose(); setTimeout(() => { setIsPremiumExport(false); setEstimatedTimeRemaining(null); setStatus('start'); exportStartTime.current = null; lastProgressTime.current = null; lastProgress.current = 0; }, 300); }; // Update status based on export progress - transition to complete immediately when 100% useEffect(() => { if (status === 'processing' && exportProgress >= 100) { setStatus('complete'); // Call premiumExportComplete immediately when export completes if (isPremiumExport) { premiumExportComplete(); } } }, [exportProgress, status, isPremiumExport, premiumExportComplete]); // Calculate estimated time remaining based on progress speed useEffect(() => { if (status !== 'processing' || exportProgress === 0) { exportStartTime.current = null; lastProgressTime.current = null; lastProgress.current = 0; setEstimatedTimeRemaining(null); return; } // Clear estimate when complete if (exportProgress >= 100) { setEstimatedTimeRemaining(0); return; } const now = Date.now(); // Initialize timing on first progress if (!exportStartTime.current) { exportStartTime.current = now; lastProgress.current = exportProgress; console.log('Initialized timing at', exportProgress + '%'); return; } // Calculate every time progress changes after initial 3 seconds const timeSinceStart = now - exportStartTime.current; const progressDelta = exportProgress - lastProgress.current; console.log( 'Progress:', exportProgress + '%', 'Time since start:', Math.round(timeSinceStart / 1000) + 's', 'Progress delta:', progressDelta + '%', ); if (timeSinceStart > 2000 && progressDelta > 0) { const progressRate = progressDelta / timeSinceStart; // progress per ms const remainingProgress = 100 - exportProgress; const estimatedMs = remainingProgress / progressRate; const estimatedSeconds = Math.round(estimatedMs / 1000); console.log('Progress rate:', progressRate, 'Estimated seconds:', estimatedSeconds); if (estimatedSeconds >= 1 && estimatedSeconds <= 600) { setEstimatedTimeRemaining(estimatedSeconds); console.log('Set estimated time:', estimatedSeconds + 's'); } else { console.log('Time estimate out of range:', estimatedSeconds + 's'); } } }, [status, exportProgress]); const formatTimeRemaining = (seconds) => { if (seconds < 60) { return `~${seconds}s remaining`; } else { const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; return `~${minutes}m ${remainingSeconds}s remaining`; } }; const exportTimes = [ { icon: '🐇', label: 'Modern and fast devices', time: '1-2 mins', }, { icon: '🐢', label: 'Medium range devices', time: '3-5 mins', }, { icon: '🥔', label: 'Older / potato devices', time: '>5 mins', }, ]; return ( status === 'processing' && e.preventDefault()} onEscapeKeyDown={(e) => status === 'processing' && e.preventDefault()} > Export Video {status === 'start' && (

Estimated export time

{exportTimes.map((exportTime, index) => (
{exportTime.icon} {exportTime.label}
{exportTime.time}
))}
{nonWatermarkVideosLeft > 0 && ( )}
{showDebug &&