diff options
| author | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
| commit | e837e7504379e100ff3b56282577ec67bb88bec9 (patch) | |
| tree | eec7e6f964725a783a9e907e931862591bb46b55 /apps/web/src/actions/freeze-frame-store.ts | |
| parent | da99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (diff) | |
| download | opencut-e837e7504379e100ff3b56282577ec67bb88bec9.tar.gz | |
feat: ripple-extend resize, timeline filmstrip, export hardening
Yesterday's verified web session (gates green: 316 tests, tsc, build):
- ripple-extend pushes right-hand chain on static-element resize
- per-position video filmstrip thumbnails with zoom-adaptive density
- fps-aware export bitrate, 2s keyframes, even-dim export canvas
- freeze frame uses fixed 3s duration, prompt removed
Diffstat (limited to 'apps/web/src/actions/freeze-frame-store.ts')
| -rw-r--r-- | apps/web/src/actions/freeze-frame-store.ts | 72 |
1 files changed, 0 insertions, 72 deletions
diff --git a/apps/web/src/actions/freeze-frame-store.ts b/apps/web/src/actions/freeze-frame-store.ts deleted file mode 100644 index 17102780..00000000 --- a/apps/web/src/actions/freeze-frame-store.ts +++ /dev/null @@ -1,72 +0,0 @@ -"use client"; - -import { create } from "zustand"; -import { persist } from "zustand/middleware"; - -export const DEFAULT_FREEZE_DURATION_SECONDS = 3; -export const MAX_FREEZE_DURATION_SECONDS = 600; - -export function isValidFreezeDuration({ - seconds, -}: { - seconds: number; -}): boolean { - return ( - Number.isFinite(seconds) && - seconds > 0 && - seconds <= MAX_FREEZE_DURATION_SECONDS - ); -} - -type DurationResolver = ({ seconds }: { seconds: number | null }) => void; - -interface FreezeFrameState { - isOpen: boolean; - lastDurationSeconds: number; - resolver: DurationResolver | null; - requestDuration: () => Promise<number | null>; - confirmDuration: ({ seconds }: { seconds: number }) => void; - cancelDuration: () => void; -} - -export const useFreezeFrameStore = create<FreezeFrameState>()( - persist( - (set, get) => ({ - isOpen: false, - lastDurationSeconds: DEFAULT_FREEZE_DURATION_SECONDS, - resolver: null, - - requestDuration: () => - new Promise<number | null>((resolve) => { - // A new invocation supersedes any pending one: resolve it as - // cancelled so its handler aborts instead of hanging. - get().resolver?.({ seconds: null }); - set({ - isOpen: true, - resolver: ({ seconds }) => resolve(seconds), - }); - }), - confirmDuration: ({ seconds }) => { - if (!isValidFreezeDuration({ seconds })) { - return; - } - get().resolver?.({ seconds }); - set({ - isOpen: false, - resolver: null, - lastDurationSeconds: seconds, - }); - }, - cancelDuration: () => { - get().resolver?.({ seconds: null }); - set({ isOpen: false, resolver: null }); - }, - }), - { - name: "freeze-frame-store", - partialize: (state) => ({ - lastDurationSeconds: state.lastDurationSeconds, - }), - }, - ), -); |
