import { FileImageOutlined, PlusOutlined, ThunderboltOutlined, VideoCameraOutlined, } from "@ant-design/icons"; import { useMemo, useRef, useState, type ChangeEvent, type DragEvent, type KeyboardEvent, type MouseEvent as ReactMouseEvent, type RefObject } from "react"; import { createPortal } from "react-dom"; import EcommerceVideoWorkspace from "../EcommerceVideoWorkspace"; interface CloneImageItem { id: string; src: string; name: string; file?: File; } type CloneVideoQualityKey = "standard" | "high" | "ultra"; interface EcommerceOneClickVideoPanelProps { onClose: () => void; isAuthenticated: boolean; onRequestLogin: () => void; productImages: CloneImageItem[]; productInputRef: RefObject; isProductUploadDragging: boolean; setIsProductUploadDragging: (value: boolean) => void; handleProductDrop: (event: DragEvent) => void; handleProductUpload: (event: ChangeEvent) => void; removeProductImage: (imageId: string) => void; maxProductImages: number; requirement: string; onRequirementChange: (value: string) => void; platform: string; platformOptions: string[]; onPlatformChange: (value: string) => void; ratio: string; ratioOptions: string[]; onRatioChange: (value: string) => void; videoQuality: CloneVideoQualityKey; videoQualityOptions: Array<{ key: CloneVideoQualityKey; label: string; desc: string }>; onVideoQualityChange: (value: CloneVideoQualityKey) => void; videoDuration: number; videoDurationMin: number; videoDurationMax: number; onVideoDurationChange: (value: number) => void; videoSmart: boolean; onVideoSmartChange: (value: boolean) => void; onOpenHistory: () => void; } function getVideoAspectRatio(ratio: string): string { if (ratio.includes("9:16")) return "9:16"; if (ratio.includes("16:9")) return "16:9"; if (ratio.includes("3:4")) return "3:4"; return "9:16"; } function openQuickUploadWithKeyboard( event: KeyboardEvent, inputRef: { current: HTMLInputElement | null }, ) { if (event.key !== "Enter" && event.key !== " ") return; event.preventDefault(); inputRef.current?.click(); } export default function EcommerceOneClickVideoPanel({ onClose, isAuthenticated, onRequestLogin, productImages, productInputRef, isProductUploadDragging, setIsProductUploadDragging, handleProductDrop, handleProductUpload, removeProductImage, maxProductImages, requirement, onRequirementChange, platform, platformOptions, onPlatformChange, ratio, ratioOptions, onRatioChange, videoQuality, videoQualityOptions, onVideoQualityChange, videoDuration, videoDurationMin, videoDurationMax, onVideoDurationChange, videoSmart, onVideoSmartChange, onOpenHistory, }: EcommerceOneClickVideoPanelProps) { const [openSelect, setOpenSelect] = useState<"platform" | "ratio" | null>(null); const [planTrigger, setPlanTrigger] = useState(0); const [hoverZoom, setHoverZoom] = useState<{ src: string; x: number; y: number; placement: "right" | "left" } | null>(null); const selectAnchorRef = useRef(null); const productImageDataUrls = useMemo(() => productImages.map((img) => img.src), [productImages]); const productImageFiles = useMemo(() => productImages.map((img) => img.file), [productImages]); const canGenerate = productImages.length > 0 || requirement.trim().length > 0; const handleGenerate = () => { if (!isAuthenticated) { onRequestLogin(); return; } setPlanTrigger((value) => value + 1); }; const handlePlatformSelect = (value: string) => { onPlatformChange(value); setOpenSelect(null); }; const handleRatioSelect = (value: string) => { onRatioChange(value); setOpenSelect(null); }; const toggleSelect = (key: "platform" | "ratio") => { setOpenSelect((current) => (current === key ? null : key)); }; const handleThumbMouseEnter = (src: string, event: ReactMouseEvent) => { const rect = event.currentTarget.getBoundingClientRect(); const previewWidth = 300; const previewHeight = 190; const gap = 12; const viewportWidth = window.innerWidth || document.documentElement.clientWidth; const viewportHeight = window.innerHeight || document.documentElement.clientHeight; const canShowRight = rect.right + gap + previewWidth <= viewportWidth - gap; const placement: "right" | "left" = canShowRight ? "right" : "left"; const x = placement === "right" ? rect.right + gap : Math.max(gap, rect.left - gap); const y = Math.min( Math.max(rect.top + rect.height / 2, previewHeight / 2 + gap), Math.max(previewHeight / 2 + gap, viewportHeight - previewHeight / 2 - gap), ); setHoverZoom({ src, x, y, placement }); }; const renderThumbs = () => (
{productImages.map((item) => (
handleThumbMouseEnter(item.src, event)} onMouseLeave={() => setHoverZoom(null)} > {item.name}
))}
); return (