import React, { useEffect, useState } from "react"; import { Play, RotateCcw, X } from "lucide-react"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { cn, formatFileSize } from "@/lib/utils"; import { useFileUpload } from "@/hooks/use-file-upload"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Drawer, DrawerClose, DrawerContent, DrawerFooter, DrawerPortal, } from "@/components/ui/drawer"; import { CopyButton } from "@/components/shared/copy-button"; import { Icons } from "@/components/shared/icons"; import { BucketInfo, BucketUsage, StorageUserPlan } from "."; import DragAndDrop from "./drag-and-drop"; export const FileUploader = ({ bucketInfo, action, plan, userId, bucketUsage, }: { bucketInfo: BucketInfo; action: string; userId: string; plan?: StorageUserPlan; bucketUsage: BucketUsage; onRefresh: () => void; }) => { const t = useTranslations("Components"); const [isOpen, setIsOpen] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const { files, isUploading, stats, addFiles, removeFile, cancelUpload, retryUpload, startUpload, clearAll, } = useFileUpload({ api: `${action}/s3/upload`, bucketInfo, userId }); useEffect(() => { if (selectedFile) { const outOfLimitSizeFiles = selectedFile.some( (file) => file.size > Number(plan?.stMaxFileSize ?? 0), ); const notOutOfLimitSizeFiles = selectedFile.filter( (file) => file.size <= Number(plan?.stMaxFileSize ?? 0), ); addFiles(notOutOfLimitSizeFiles); if (outOfLimitSizeFiles) { toast.warning( `File size exceeds the limit of ${formatFileSize( Number(plan?.stMaxFileSize ?? 0), )}`, ); } } }, [selectedFile]); return ( <> {isOpen && (

{t("Upload Files")}

{bucketInfo.provider_name}
{bucketInfo.bucket}
{t("Limit")}:{" "} {formatFileSize(bucketUsage.limits.maxSingleFileSize, { precision: 1, })}{" "} /{" "} {formatFileSize(bucketUsage.limits.maxStorage, { precision: 0, })}
{/* 统计信息 */} {stats.total > 0 && (

{t("Upload List")}

{stats.completed} / {stats.total}
//
//
// 总计: {stats.total} // 等待: {stats.pending} // // 上传中: {stats.uploading} // // // 完成: {stats.completed} // // 失败: {stats.error} // // 取消: {stats.cancelled} // //
//
)} {/* 文件列表 */} {files.length > 0 && (
{files.some((file) => file.status === "uploading") && (
{t( "Do not close the window until the upload is complete", )} .
)} {/* 文件列表 */} {files.map((file) => (
{/* 主进度条背景 */} {file.status === "uploading" && (
)} {/* 内容区域 */}

{file.originalName}

{formatFileSize(file.file.size)}

{/* 状态指示器和操作按钮 */}
{file.status === "pending" ? (
{t("Pending Upload")}
) : file.status === "uploading" ? (
{file.progress}%
{t("Uploading")}
) : file.status === "completed" ? (
{t("Completed")}
) : ( (file.status === "error" || file.status === "cancelled") && (
{file.status === "cancelled" ? t("Aborted") : t("Failed")}
{file.status === "error" && file.error && (
{file.error}
)}
) )}
{/* 进度条 */} {file.status === "uploading" && (
0 && file.progress < 100 ? 1 : 0, }} />
)}
))}
)}
{files.length > 0 && (
)}
)} ); };