auto-save 2026-05-12 23:55 (~2)

This commit is contained in:
2026-05-12 23:55:21 +08:00
parent 25a1e636e1
commit fd4c78f697
2 changed files with 21 additions and 10 deletions

View File

@@ -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
}
]
}

View File

@@ -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>