zone previews

This commit is contained in:
2026-04-15 20:27:24 -06:00
parent 4d3d8a2218
commit af8e0cf6eb
4 changed files with 156 additions and 19 deletions

View File

@ -43,6 +43,7 @@ interface EditorState {
exportProgress: number;
backendUrl: string;
zonePreviewPaddingSeconds: number;
}
interface EditorActions {
@ -82,12 +83,23 @@ interface EditorActions {
removeSilenceTrimGroup: (groupId: string) => void;
setTranscribing: (active: boolean, progress?: number, status?: string) => void;
setExporting: (active: boolean, progress?: number) => void;
setZonePreviewPaddingSeconds: (seconds: number) => void;
getKeepSegments: () => Array<{ start: number; end: number }>;
getWordAtTime: (time: number) => number;
loadProject: (projectData: any) => void;
reset: () => void;
}
const ZONE_PREVIEW_PADDING_KEY = 'talkedit-zone-preview-padding-seconds';
function getStoredZonePreviewPaddingSeconds() {
if (typeof window === 'undefined') return 1;
const stored = window.localStorage.getItem(ZONE_PREVIEW_PADDING_KEY);
const parsed = stored ? Number(stored) : 1;
if (!Number.isFinite(parsed)) return 1;
return Math.max(0, Math.min(10, parsed));
}
const initialState: EditorState = {
videoPath: null,
videoUrl: null,
@ -113,6 +125,7 @@ const initialState: EditorState = {
isExporting: false,
exportProgress: 0,
backendUrl: 'http://127.0.0.1:8000',
zonePreviewPaddingSeconds: getStoredZonePreviewPaddingSeconds(),
};
let nextRangeId = 1;
@ -184,11 +197,12 @@ export const useEditorStore = create<EditorState & EditorActions>()(
},
loadVideo: (path) => {
const backend = get().backendUrl;
const url = `${backend}/file?path=${encodeURIComponent(path)}`;
const { backendUrl, zonePreviewPaddingSeconds } = get();
const url = `${backendUrl}/file?path=${encodeURIComponent(path)}`;
set({
...initialState,
backendUrl: backend,
backendUrl,
zonePreviewPaddingSeconds,
videoPath: path,
videoUrl: url,
});
@ -407,6 +421,14 @@ export const useEditorStore = create<EditorState & EditorActions>()(
exportProgress: progress ?? (active ? 0 : 100),
}),
setZonePreviewPaddingSeconds: (seconds) => {
const nextSeconds = Math.max(0, Math.min(10, seconds));
if (typeof window !== 'undefined') {
window.localStorage.setItem(ZONE_PREVIEW_PADDING_KEY, String(nextSeconds));
}
set({ zonePreviewPaddingSeconds: nextSeconds });
},
getKeepSegments: () => {
const { words, cutRanges, duration } = get();
if (words.length === 0) return [{ start: 0, end: duration }];
@ -456,8 +478,8 @@ export const useEditorStore = create<EditorState & EditorActions>()(
},
loadProject: (data) => {
const backend = get().backendUrl;
const url = `${backend}/file?path=${encodeURIComponent(data.videoPath)}`;
const { backendUrl, zonePreviewPaddingSeconds } = get();
const url = `${backendUrl}/file?path=${encodeURIComponent(data.videoPath)}`;
let globalIdx = 0;
const annotatedSegments = (data.segments || []).map((seg: Segment) => {
@ -468,7 +490,8 @@ export const useEditorStore = create<EditorState & EditorActions>()(
set({
...initialState,
backendUrl: backend,
backendUrl,
zonePreviewPaddingSeconds,
videoPath: data.videoPath,
videoUrl: url,
words: data.words || [],
@ -489,7 +512,10 @@ export const useEditorStore = create<EditorState & EditorActions>()(
});
},
reset: () => set(initialState),
reset: () => {
const { zonePreviewPaddingSeconds } = get();
set({ ...initialState, zonePreviewPaddingSeconds });
},
}),
{ limit: 100 },
),