96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
"use client"
|
||
import { useRef, useState } from "react"
|
||
import { Link2, Loader2, Upload } from "lucide-react"
|
||
|
||
interface Props {
|
||
loading?: boolean
|
||
onSubmitUrl: (url: string) => void
|
||
onUploadFile: (file: File) => void
|
||
}
|
||
|
||
export function UrlInput({ loading, onSubmitUrl, onUploadFile }: Props) {
|
||
const [url, setUrl] = useState("")
|
||
const [dragOver, setDragOver] = useState(false)
|
||
const fileRef = useRef<HTMLInputElement>(null)
|
||
|
||
const pickFile = () => fileRef.current?.click()
|
||
|
||
const handleFiles = (files: FileList | null) => {
|
||
if (!files || files.length === 0) return
|
||
const f = files[0]
|
||
if (!f.type.startsWith("video/") && !/\.(mp4|mov|webm|mkv|m4v)$/i.test(f.name)) {
|
||
// sonner is in page; keep simple here
|
||
console.warn("not a video file:", f.name)
|
||
return
|
||
}
|
||
onUploadFile(f)
|
||
}
|
||
|
||
return (
|
||
<form
|
||
onSubmit={(e) => {
|
||
e.preventDefault()
|
||
const trimmed = url.trim()
|
||
if (trimmed) onSubmitUrl(trimmed)
|
||
}}
|
||
onDragOver={(e) => {
|
||
e.preventDefault()
|
||
if (!loading) setDragOver(true)
|
||
}}
|
||
onDragLeave={() => setDragOver(false)}
|
||
onDrop={(e) => {
|
||
e.preventDefault()
|
||
setDragOver(false)
|
||
if (loading) return
|
||
handleFiles(e.dataTransfer.files)
|
||
}}
|
||
className="relative w-full"
|
||
>
|
||
<div
|
||
className={`glass-card flex items-center gap-3 px-5 py-4 transition ${
|
||
dragOver ? "ring-2 ring-white/40 bg-white/[0.08]" : ""
|
||
}`}
|
||
>
|
||
<Link2 className="h-5 w-5 shrink-0 text-white/40" />
|
||
<input
|
||
value={url}
|
||
onChange={(e) => setUrl(e.target.value)}
|
||
placeholder={dragOver ? "松开以上传视频" : "粘贴 TikTok 链接,或拖入 / 上传本地视频"}
|
||
className="w-full bg-transparent text-white placeholder:text-white/30 outline-none text-[15px]"
|
||
disabled={loading}
|
||
/>
|
||
{/* 上传按钮 */}
|
||
<button
|
||
type="button"
|
||
onClick={pickFile}
|
||
disabled={loading}
|
||
className="shrink-0 inline-flex items-center gap-1.5 rounded-md border border-white/15 bg-white/5 hover:bg-white/10 px-3 py-2 text-xs text-white/80 disabled:opacity-40 disabled:cursor-not-allowed transition"
|
||
title="上传本地视频"
|
||
>
|
||
<Upload className="h-3.5 w-3.5" />
|
||
上传
|
||
</button>
|
||
{/* 提交按钮 */}
|
||
<button
|
||
type="submit"
|
||
disabled={loading || !url.trim()}
|
||
className="shrink-0 rounded-md bg-white text-black px-4 py-2 text-sm font-medium hover:bg-white/90 disabled:opacity-40 disabled:cursor-not-allowed transition inline-flex items-center gap-2"
|
||
>
|
||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
|
||
{loading ? "处理中" : "提交"}
|
||
</button>
|
||
<input
|
||
ref={fileRef}
|
||
type="file"
|
||
accept="video/mp4,video/quicktime,video/webm,video/x-matroska,.mp4,.mov,.webm,.mkv,.m4v"
|
||
className="hidden"
|
||
onChange={(e) => handleFiles(e.target.files)}
|
||
/>
|
||
</div>
|
||
<div className="mt-2 text-[11px] text-white/30 px-1">
|
||
支持:TikTok 链接 · 拖入视频文件 · 点击上传 · 格式 mp4 / mov / webm / mkv / m4v
|
||
</div>
|
||
</form>
|
||
)
|
||
}
|