summaryrefslogtreecommitdiff
path: root/apps/web/src/actions/freeze-frame-store.ts
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-28 19:41:14 +0200
committercashmere <cashmere@autistici.org>2026-07-28 19:41:14 +0200
commite837e7504379e100ff3b56282577ec67bb88bec9 (patch)
treeeec7e6f964725a783a9e907e931862591bb46b55 /apps/web/src/actions/freeze-frame-store.ts
parentda99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (diff)
downloadopencut-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.ts72
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,
- }),
- },
- ),
-);