summaryrefslogtreecommitdiff
path: root/apps/web/src/commands
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/commands
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/commands')
-rw-r--r--apps/web/src/commands/media/remove-media-asset.ts16
1 files changed, 16 insertions, 0 deletions
diff --git a/apps/web/src/commands/media/remove-media-asset.ts b/apps/web/src/commands/media/remove-media-asset.ts
index 38ff79fe..ab267f36 100644
--- a/apps/web/src/commands/media/remove-media-asset.ts
+++ b/apps/web/src/commands/media/remove-media-asset.ts
@@ -1,5 +1,6 @@
import { Command, type CommandResult } from "@/commands/base-command";
import { EditorCore } from "@/core";
+import { toast } from "sonner";
import type { MediaAsset } from "@/media/types";
import { buildWaveformSourceKey } from "@/media/waveform-summary";
import { storageService } from "@/services/storage/service";
@@ -30,6 +31,21 @@ export class RemoveMediaAssetCommand extends Command {
execute(): CommandResult | undefined {
const editor = EditorCore.getInstance();
+
+ // Media pinning: a stored project version may still reference this
+ // asset; deleting it would break restores (notes/project-versioning.md).
+ if (
+ editor.versions.isMediaIdPinned({
+ projectId: this.projectId,
+ mediaId: this.assetId,
+ })
+ ) {
+ toast.error("Media is used in a saved version", {
+ description: "Delete the checkpoints that reference it first.",
+ });
+ return;
+ }
+
const assets = editor.media.getAssets();
this.savedAssets = [...assets];