taghirsado / components /ProcessingPanel.tsx
Opera10's picture
Update components/ProcessingPanel.tsx
1467cef verified
Raw
History Blame Contribute Delete
11.3 kB
import React, { useState } from 'react';
import { JobData } from '../types';
import * as api from '../services/api';
interface ProcessingPanelProps {
job: JobData | null;
embedded?: boolean;
onEnhance?: (job: JobData) => void;
}
const ProcessingPanel: React.FC<ProcessingPanelProps> = ({ job, embedded = false, onEnhance }) => {
const [downloadingType, setDownloadingType] = useState<'main' | 'enhanced' | null>(null);
const [copySuccess, setCopySuccess] = useState(false);
if (!job) return null;
const isCompleted = job.status === 'completed';
const isFailed = job.status === 'failed' || job.status === 'error';
const VC_BASE_URL = 'https://ezmarynoori-sada.hf.space';
let downloadUrl = '#';
if (isCompleted) {
if (job.downloadUrl) {
downloadUrl = job.downloadUrl;
} else if (job.filename) {
downloadUrl = `${VC_BASE_URL}/download/${job.filename}`;
}
}
const enhanceInfo = job.enhancement;
const isEnhancing = enhanceInfo?.status === 'processing' || enhanceInfo?.status === 'started';
const isEnhanceCompleted = enhanceInfo?.status === 'completed';
// استفاده اولویت‌دار از لینک مستقیم بله که در مرورگر ذخیره شده است
const enhanceDownloadUrl = isEnhanceCompleted
? (enhanceInfo?.downloadUrl || (enhanceInfo?.filename ? api.getEnhancementDownloadUrl(enhanceInfo.filename) : '#'))
: '#';
const handleDownload = async (e: React.MouseEvent, url: string, type: 'main' | 'enhanced') => {
e.preventDefault();
if (downloadingType) return;
setDownloadingType(type);
try {
let blobUrl = url;
if (!url.startsWith('blob:')) {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`Network response was not ok: ${resp.statusText}`);
const blob = await resp.blob();
blobUrl = URL.createObjectURL(blob);
}
window.parent.postMessage({
type: 'INITIATE_DOWNLOAD_FROM_URL',
payload: { audioUrl: blobUrl }
}, '*');
} catch (err) {
console.error("Download preparation error:", err);
alert("خطا در آماده‌سازی دانلود. لطفاً اتصال اینترنت خود را بررسی کنید.");
} finally {
setDownloadingType(null);
}
};
const handleCopyErrorLog = () => {
const logText = job.statusMessage || 'Unknown Error';
navigator.clipboard.writeText(logText).then(() => {
setCopySuccess(true);
setTimeout(() => setCopySuccess(false), 2000);
}).catch(err => {
console.error('Failed to copy error log', err);
});
};
const containerClasses = embedded
? "bg-gray-50/80 rounded-lg p-3 mt-2 border border-gray-100 animate-[fadeIn_0.3s_ease-out]"
: "bg-white rounded-3xl shadow-lg border border-gray-100 p-6 mt-6 animate-[slideUp_0.5s_ease-out]";
return (
<div className={containerClasses}>
<div className="flex items-center justify-between mb-2">
<div>
<h4 className={`font-bold text-gray-800 ${embedded ? 'text-xs' : 'text-lg'}`}>
{isCompleted ? 'فایل اصلی آماده' : isFailed ? 'خطا در پردازش' : 'در حال تغییر صدا...'}
</h4>
{!embedded && (
<p className="text-xs text-gray-500">
{job.type === 'model' ? `مدل: ${job.modelName}` : 'اختصاصی'}
</p>
)}
</div>
{!embedded && (
<div className={`w-10 h-10 rounded-full flex items-center justify-center text-white shadow-md
${isCompleted ? 'bg-green-500' : isFailed ? 'bg-red-500' : 'bg-amber-400'}`}>
<i className={`fas ${isCompleted ? 'fa-check' : isFailed ? 'fa-exclamation' : 'fa-cog fa-spin'}`}></i>
</div>
)}
</div>
{!isCompleted && !isFailed && (
<div className="mb-2">
{!embedded && (
<div className="flex justify-between text-xs text-gray-500 mb-1">
<span>پیشرفت کلی</span>
<span>{job.progress || 0}%</span>
</div>
)}
<div className={`w-full bg-gray-200 rounded-full overflow-hidden ${embedded ? 'h-1.5' : 'h-2'}`}>
<div
className="h-full bg-gradient-to-r from-amber-400 to-orange-500 rounded-full transition-all duration-500 relative"
style={{ width: `${job.progress || 0}%` }}
>
<div className="absolute inset-0 bg-white/20 w-full h-full animate-[shimmer_2s_infinite]"></div>
</div>
</div>
<p className="text-center text-[10px] text-gray-500 mt-2 font-medium truncate px-1">
{job.statusMessage || 'در حال انجام عملیات...'}
</p>
</div>
)}
{isCompleted && (
<div className={`${embedded ? 'mt-1' : 'mt-4 pt-4 border-t border-gray-100'}`}>
<audio controls className={`w-full ${embedded ? 'mb-2 h-7' : 'mb-3 h-8'}`} src={downloadUrl} />
<a
href="#"
onClick={(e) => handleDownload(e, downloadUrl, 'main')}
className={`block w-full text-center text-white rounded-xl font-bold transition-all shadow-sm flex items-center justify-center gap-2
${embedded ? 'py-2 text-xs bg-gray-600 hover:bg-gray-700' : 'py-3 bg-gray-600 shadow-gray-200'}
${downloadingType === 'main' ? 'opacity-70 cursor-wait' : ''}`}
>
{downloadingType === 'main' ? (
<><i className="fas fa-circle-notch fa-spin"></i> آماده‌سازی...</>
) : (
<><i className="fas fa-download"></i> دانلود صدای اصلی (معمولی)</>
)}
</a>
</div>
)}
{isFailed && (
<div
onClick={handleCopyErrorLog}
className="mt-1 p-2 bg-red-50 text-red-600 rounded-lg text-[10px] text-center border border-red-100 cursor-pointer hover:bg-red-100 transition-colors relative group"
>
{copySuccess ? (
<span className="font-bold text-green-600 animate-pulse">
<i className="fas fa-check mr-1"></i> متن خطا کپی شد
</span>
) : (
<span className="flex items-center justify-center gap-1">
خطا در پردازش.
</span>
)}
</div>
)}
{isCompleted && onEnhance && (
<div className={`mt-4 pt-4 border-t-2 border-dashed ${isEnhanceCompleted ? 'border-amber-200 bg-amber-50/50 -mx-3 px-3 pb-3 rounded-b-xl' : 'border-gray-100'}`}>
{!enhanceInfo && (
<button
onClick={() => onEnhance(job)}
className="group relative w-full overflow-hidden rounded-xl bg-gradient-to-r from-violet-600 to-indigo-600 p-[2px] transition-all hover:shadow-lg hover:shadow-indigo-500/30 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-offset-2 active:scale-95"
>
<div className="relative flex items-center justify-center gap-2 rounded-[10px] bg-white px-4 py-2.5 transition-all group-hover:bg-transparent group-hover:text-white">
<i className="fas fa-wand-magic-sparkles text-lg text-indigo-600 transition-colors group-hover:text-white animate-pulse"></i>
<span className="font-black text-sm text-gray-800 transition-colors group-hover:text-white">
افزایش کیفیت صدا و حذف نویز (AI)
</span>
</div>
</button>
)}
{enhanceInfo && isEnhancing && (
<div className="animate-[fadeIn_0.5s_ease-out]">
<div className="flex items-center justify-between mb-2">
<span className="text-xs font-bold text-indigo-700 flex items-center gap-2">
<i className="fas fa-sparkles fa-spin text-amber-500"></i>
در حال حذف نویز و تقویت صدا...
</span>
<span className="text-[11px] font-black text-indigo-600">{enhanceInfo.progress || 0}%</span>
</div>
<div className="h-3 w-full rounded-full bg-indigo-100 overflow-hidden shadow-inner">
<div
className="h-full rounded-full bg-gradient-to-r from-violet-500 via-fuchsia-500 to-indigo-500 transition-all duration-500 ease-out relative"
style={{ width: `${Math.max(5, enhanceInfo.progress || 0)}%` }}
>
<div className="absolute inset-0 bg-white/30 w-full h-full animate-[shimmer_1.5s_infinite]"></div>
</div>
</div>
<p className="text-[9px] text-center text-indigo-400 mt-1 font-bold">در حال انجام کار ممکن است زمان‌بر باشد</p>
</div>
)}
{enhanceInfo && isEnhanceCompleted && (
<div className="animate-[scaleIn_0.4s_cubic-bezier(0.175,0.885,0.32,1.275)]">
<div className="flex items-center gap-2 mb-2 justify-center">
<i className="fas fa-star text-amber-400 text-sm animate-[spin_3s_linear_infinite]"></i>
<h5 className="text-xs font-black text-amber-700">نسخه تقویت شده (High Quality)</h5>
<i className="fas fa-star text-amber-400 text-sm animate-[spin_3s_linear_infinite_reverse]"></i>
</div>
<audio controls className="w-full h-7 mb-2 border border-amber-200 rounded-full bg-amber-100" src={enhanceDownloadUrl} />
<a
href="#"
onClick={(e) => handleDownload(e, enhanceDownloadUrl, 'enhanced')}
className={`block w-full text-center text-white rounded-xl font-bold bg-gradient-to-r from-amber-500 to-orange-500 py-2.5 text-xs shadow-lg shadow-amber-500/30 hover:shadow-amber-500/50 transition-all transform hover:-translate-y-0.5 active:translate-y-0
${downloadingType === 'enhanced' ? 'opacity-70 cursor-wait' : ''}`}
>
{downloadingType === 'enhanced' ? (
<><i className="fas fa-circle-notch fa-spin mr-1"></i> در حال آماده‌سازی...</>
) : (
<><i className="fas fa-download mr-1"></i> دانلود صدای با کیفیت عالی</>
)}
</a>
</div>
)}
{enhanceInfo?.status === 'failed' && (
<div className="text-xs text-red-500 bg-red-50 p-2 rounded border border-red-100 text-center font-bold">
خطا در تقویت صدا. لطفا دوباره تلاش کنید.
</div>
)}
</div>
)}
</div>
);
};
export default ProcessingPanel;