summaryrefslogtreecommitdiff
path: root/apps/web/src/versions/media-references.ts
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-27 01:21:20 +0200
committercashmere <cashmere@autistici.org>2026-07-27 01:21:20 +0200
commitd55d2583a71ae35fa8d0d1bfbec975e67e66aafa (patch)
treec7a612f24b12c8602d7fbf139ac2709e4f2f4d9c /apps/web/src/versions/media-references.ts
parent2a372fdec256b8be890e181c221c2a012ead9efa (diff)
downloadopencut-d55d2583a71ae35fa8d0d1bfbec975e67e66aafa.tar.gz
feat: git-like project versioning (v1)
Linear per-project history per notes/project-versioning.md: named checkpoints (thumbnail via renderer.captureFrame) plus auto-checkpoints on save (60s throttle, ring of 20, named never rotate). Restore writes a safety checkpoint first, then swaps the document outside undo/redo. Media assets referenced by any version are pinned against deletion. Migration v31-v32 stamps the schema; the version store lives in its own IDB database with an in-memory fallback for tests. Versions popover in the editor header for jump/rename/delete. 12 new tests.
Diffstat (limited to 'apps/web/src/versions/media-references.ts')
-rw-r--r--apps/web/src/versions/media-references.ts52
1 files changed, 52 insertions, 0 deletions
diff --git a/apps/web/src/versions/media-references.ts b/apps/web/src/versions/media-references.ts
new file mode 100644
index 00000000..86264320
--- /dev/null
+++ b/apps/web/src/versions/media-references.ts
@@ -0,0 +1,52 @@
+import type { SerializedProject } from "@/services/storage/types";
+
+function isRecord(value: unknown): value is Record<string, unknown> {
+ return typeof value === "object" && value !== null && !Array.isArray(value);
+}
+
+function collectFromElements({
+ elements,
+ mediaIds,
+}: {
+ elements: unknown;
+ mediaIds: Set<string>;
+}): void {
+ if (!Array.isArray(elements)) return;
+
+ for (const element of elements) {
+ if (!isRecord(element)) continue;
+ if (typeof element.mediaId === "string" && element.mediaId.length > 0) {
+ mediaIds.add(element.mediaId);
+ }
+ }
+}
+
+/**
+ * Extracts every media asset id referenced by a serialized project's scenes.
+ * Duck-typed (like migrations) so snapshots of any project version scan safely.
+ */
+export function getReferencedMediaIds({
+ project,
+}: {
+ project: SerializedProject;
+}): Set<string> {
+ const mediaIds = new Set<string>();
+
+ for (const scene of project.scenes ?? []) {
+ const tracks: unknown = scene.tracks;
+ if (!isRecord(tracks)) continue;
+
+ if (isRecord(tracks.main)) {
+ collectFromElements({ elements: tracks.main.elements, mediaIds });
+ }
+ for (const list of [tracks.overlay, tracks.audio]) {
+ if (!Array.isArray(list)) continue;
+ for (const track of list) {
+ if (!isRecord(track)) continue;
+ collectFromElements({ elements: track.elements, mediaIds });
+ }
+ }
+ }
+
+ return mediaIds;
+}