auto-save 2026-05-12 23:55 (~2)
This commit is contained in:
@@ -489,6 +489,13 @@
|
||||
"message": "auto-save 2026-05-12 23:44 (~2)",
|
||||
"hash": "494d990",
|
||||
"files_changed": 2
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-12T23:49:50+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-12 23:49 (~2)",
|
||||
"hash": "25a1e63",
|
||||
"files_changed": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,9 +27,10 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
const inField = ["INPUT", "TEXTAREA"].includes((e.target as HTMLElement).tagName)
|
||||
if (e.key === "Escape") onClose()
|
||||
if (!inField) {
|
||||
if (e.key === "ArrowLeft" && activeIndex > 0) onChange(activeIndex - 1)
|
||||
if (e.key === "ArrowRight" && activeIndex < frames.length - 1) onChange(activeIndex + 1)
|
||||
if (!inField && activeIndex !== null) {
|
||||
const pos = frames.findIndex((x) => x.index === activeIndex)
|
||||
if (e.key === "ArrowLeft" && pos > 0) onChange(frames[pos - 1].index)
|
||||
if (e.key === "ArrowRight" && pos < frames.length - 1) onChange(frames[pos + 1].index)
|
||||
if (e.key === " " || e.key === "Enter") {
|
||||
e.preventDefault()
|
||||
onToggleSelect(activeIndex)
|
||||
@@ -40,8 +41,11 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
return () => window.removeEventListener("keydown", onKey)
|
||||
}, [activeIndex, frames.length, onClose, onChange, onToggleSelect])
|
||||
|
||||
if (activeIndex === null || !frames[activeIndex] || !mounted) return null
|
||||
const f = frames[activeIndex]
|
||||
// activeIndex 是 KeyFrame.index 稳定 ID,而 frames 数组按 timestamp 排序——必须用 find 不能用 [index]
|
||||
const f = activeIndex !== null ? frames.find((x) => x.index === activeIndex) : undefined
|
||||
const arrayPos = f ? frames.findIndex((x) => x.index === f.index) : -1
|
||||
|
||||
if (activeIndex === null || !f || !mounted) return null
|
||||
const isSelected = selected.has(f.index)
|
||||
const desc = f.description
|
||||
|
||||
@@ -79,21 +83,21 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-white/10 bg-white/[0.03]">
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); if (activeIndex > 0) onChange(activeIndex - 1) }}
|
||||
disabled={activeIndex === 0}
|
||||
onClick={(e) => { e.stopPropagation(); if (arrayPos > 0) onChange(frames[arrayPos - 1].index) }}
|
||||
disabled={arrayPos <= 0}
|
||||
className="h-7 w-7 rounded-md bg-white/10 hover:bg-white/20 text-white inline-flex items-center justify-center disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); if (activeIndex < frames.length - 1) onChange(activeIndex + 1) }}
|
||||
disabled={activeIndex >= frames.length - 1}
|
||||
onClick={(e) => { e.stopPropagation(); if (arrayPos < frames.length - 1) onChange(frames[arrayPos + 1].index) }}
|
||||
disabled={arrayPos >= frames.length - 1}
|
||||
className="h-7 w-7 rounded-md bg-white/10 hover:bg-white/20 text-white inline-flex items-center justify-center disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</button>
|
||||
<span className="text-[11px] font-mono text-white/70 ml-1">
|
||||
分镜 {String(f.index + 1).padStart(2, "0")} / {String(frames.length).padStart(2, "0")}
|
||||
分镜 {String(arrayPos + 1).padStart(2, "0")} / {String(frames.length).padStart(2, "0")}
|
||||
<span className="mx-1.5 text-white/30">·</span>
|
||||
<span className="text-white/60">{f.timestamp.toFixed(2)}s</span>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user