This commit is contained in:
2026-03-27 22:57:45 -03:00
parent 94c7b21ae5
commit 1c6af767eb
4 changed files with 360 additions and 275 deletions

View File

@@ -0,0 +1,98 @@
import { ref, computed, watch } from 'vue'
import type { Ref } from 'vue'
import type { DataSource } from 'mpr-ui-framework'
import { usePipelineStore } from '../stores/pipeline'
interface CheckpointFrame {
seq: number
timestamp: number
jpeg_b64: string
}
export function useCheckpointLoader(
jobId: Ref<string>,
source: DataSource,
) {
const pipeline = usePipelineStore()
const currentFrameImage = ref<string | null>(null)
const currentFrameRef = ref<number | null>(null)
const checkpointFrames = ref<CheckpointFrame[]>([])
const checkpointFrameIndex = ref(0)
const checkpointStage = ref<string | null>(null)
const stripSelStart = ref(0)
const stripSelEndOverride = ref<number | null>(null)
const stripSelEnd = computed(() =>
stripSelEndOverride.value ?? Math.max(0, checkpointFrames.value.length - 1),
)
// Track current frame from SSE
source.on<{ frame_ref: number; jpeg_b64: string }>('frame_update', (e) => {
currentFrameImage.value = e.jpeg_b64
currentFrameRef.value = e.frame_ref
})
async function loadCheckpoint(job: string, stage: string) {
try {
const resp = await fetch(`/api/detect/checkpoints/${job}/${stage}`)
if (!resp.ok) return
const data = await resp.json()
checkpointFrames.value = data.frames ?? []
checkpointStage.value = stage
if (checkpointFrames.value.length > 0) {
checkpointFrameIndex.value = 0
const first = checkpointFrames.value[0]
currentFrameImage.value = first.jpeg_b64
currentFrameRef.value = first.seq
}
stripSelStart.value = 0
stripSelEndOverride.value = null
} catch (e) {
console.error('Failed to load checkpoint:', e)
}
}
function setCheckpointFrame(index: number) {
if (index < 0 || index >= checkpointFrames.value.length) return
checkpointFrameIndex.value = index
const frame = checkpointFrames.value[index]
currentFrameImage.value = frame.jpeg_b64
currentFrameRef.value = frame.seq
}
// Auto-load checkpoint when entering editor mode
watch(
() => [pipeline.layoutMode, pipeline.editorStage, jobId.value] as const,
([mode, stage, job]) => {
if (mode === 'bbox_editor' && stage && job) {
const stageMap: Record<string, string> = {
detect_edges: 'filter_scenes',
detect_contours: 'detect_edges',
detect_color: 'detect_contours',
merge_regions: 'detect_color',
}
const cpStage = stageMap[stage] ?? 'filter_scenes'
loadCheckpoint(job, cpStage)
}
},
{ immediate: true },
)
return {
currentFrameImage,
currentFrameRef,
checkpointFrames,
checkpointFrameIndex,
checkpointStage,
stripSelStart,
stripSelEnd,
stripSelEndOverride,
loadCheckpoint,
setCheckpointFrame,
}
}