summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-27 01:22:54 +0200
committercashmere <cashmere@autistici.org>2026-07-27 01:22:54 +0200
commitda99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (patch)
treeb7600953cc7526c677142cb837e99dee480c95c5
parent9c3b788b47cc639ee463dd07e1a4cce91e6376cc (diff)
downloadopencut-da99dec8a2de1f3849aebbf5695c1e812b2dbdf9.tar.gz
docs: record completed roadmap slices
AGENTS.md gains the versions/voiceover/transfer domains and the features flag module; roadmap marks slices 1-6 done and notes deletion of flagged-off code as the next strip step.
-rw-r--r--AGENTS.md8
-rw-r--r--notes/roadmap.md64
2 files changed, 32 insertions, 40 deletions
diff --git a/AGENTS.md b/AGENTS.md
index 7e8f7232..8aa0e32e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -32,6 +32,10 @@ Typical flow (split at playhead, key "s"): keybindings-store → `invokeAction("
| `apps/web/src/media/` | Media processing, thumbnails, upload, mediabunny wrappers |
| `apps/web/src/services/` | `renderer/` (GPU), `storage/` (IndexedDB + versioned migrations), `transcription/`, caches |
| `apps/web/src/wasm/` | `@/wasm` wrapper over `opencut-wasm` — only `wasm/media-time.ts` imports the package directly |
+| `apps/web/src/versions/` | Git-like project versioning: version store (IDB + in-memory), `VersionsManager`, media pinning, versions popover UI |
+| `apps/web/src/voiceover/` | Voice-over recording (MediaRecorder) → audio asset → timeline insert, one undo step |
+| `apps/web/src/project/transfer/` | Single-file `.ocp` import/export (fflate zip: project.json + media + manifest) |
+| `apps/web/src/features.ts` | `FEATURES` flags hiding unfinished upstream domains (sounds/stickers/effects) from the UI |
| `apps/web/src/components/` | Shared React: `ui/` (shadcn-style radix), `editor/`, `providers/` |
| `apps/web/src/app/` | App Router pages + `api/` routes |
| `rust/crates/` | Shared Rust crates; `rust/wasm/` compiles them to the `opencut-wasm` npm package |
@@ -115,7 +119,7 @@ Self-hosting: `docker compose up -d` (full stack at http://localhost:3100; postg
### Freeze frame (implemented, working)
-The timeline toolbar snowflake button (upstream had it disabled with a "coming soon" tooltip) now freezes the frame at the playhead: it captures the composited canvas as PNG, adds it as an image media asset, splits the video element at the playhead, shifts the right part right by the freeze duration, and inserts a 3-second image element in the gap.
+The timeline toolbar snowflake button freezes the frame at the playhead: a duration prompt (persisted last-used value, cancel aborts cleanly), then it captures the composited canvas as PNG, adds it as an image media asset, splits the video element at the playhead, shifts the right part right by the freeze duration, and inserts the still image element in the gap — as ONE undo step (`BatchCommand` + `ShiftSplitRemainderCommand`).
Files:
@@ -128,7 +132,7 @@ Files:
Behavior details and known limitations:
-- Freeze duration is a fixed 3 seconds (`mediaTimeFromSeconds({ seconds: 3 })` in the handler); adjust by trimming the inserted element.
+- Freeze duration comes from the prompt store (`actions/freeze-frame-store.ts`), default/last-used prefilled.
- The still is a composite capture of the whole canvas at the current time — overlays, text, and stickers visible at that moment are baked in. CapCut freezes only the clip itself; per-clip capture would need a single-element render pass.
- Target is the first selected video element under the playhead (or the first video element under the playhead if nothing is selected). With stacked videos on several tracks it may pick a non-topmost one.
- One freeze is a single undo step: the handler builds one `BatchCommand` (`AddMediaAssetCommand` + `SplitElementsCommand` + `ShiftSplitRemainderCommand` + `InsertElementCommand`) and executes it once via `editor.command.execute`.
diff --git a/notes/roadmap.md b/notes/roadmap.md
index 304957df..c886edeb 100644
--- a/notes/roadmap.md
+++ b/notes/roadmap.md
@@ -1,32 +1,27 @@
# Roadmap & session notes
-Working notes for the fork's development direction. Captured 2026-07-26
-(last commit `2f5ff9fe`; everything below "Done" is committed).
+Working notes for the fork's development direction. Captured 2026-07-26,
+updated 2026-07-27 (roadmap feature slices implemented, last commit
+`9c3b788b`).
## Done
- Freeze frame at playhead (snowflake button), composite canvas capture.
- Freeze frame is a single undo step (`BatchCommand` + `ShiftSplitRemainderCommand`).
+- Freeze-duration prompt (persisted last-used, cancel-safe; `actions/freeze-frame-store.ts`).
- `MediaPreview` no longer crashes on image assets without `url` (thumbnail → placeholder fallback).
- Test suite runs on NixOS/bun 1.3 via `bunfig.toml` preload mock of `opencut-wasm`.
- Root `justfile` wraps common commands; `just` is in the nix devshell.
+- Landing page stripped (`/` → `/projects`); Discord links + feedback UI removed.
+- Sounds/stickers/effects UI gated behind `src/features.ts` flags (all off; code kept, entry points hidden).
+- Project versioning v1 (`versions/`): named checkpoints + auto-checkpoints, restore with safety checkpoint, media pinning, versions popover. See notes/project-versioning.md.
+- Single-file `.ocp` import/export (`project/transfer/`): zip with project.json + media + manifest, migrates older archives, full round-trip tested.
+- Voice-over recording (`voiceover/`): mic → audio asset → timeline at playhead, one undo step.
Pending verification: freeze + single Ctrl+Z is unit-tested but never
-smoke-tested by hand in a running browser.
-
-## Tomorrow: freeze-duration prompt
-
-Replace the hardcoded 3 s (`mediaTimeFromSeconds({ seconds: 3 })` in the
-`freeze-frame` handler, `apps/web/src/actions/use-editor-actions.ts`) with a
-small dialog asking for the duration before capture. Notes:
-
-- Dialog components live in `apps/web/src/components/ui/` (shadcn-style radix).
-- Keep the value a `MediaTime` (`mediaTimeFromSeconds`); validate > 0.
-- Nice touch: remember the last-used duration in a zustand UI store
- (`*-store.ts`, UI/preference state only — never document state).
-- The action is invoked from the toolbar button and (if bound) the shortcuts
- UI; the prompt should appear for both paths, so put it in the handler, not
- the toolbar.
+smoke-tested by hand in a running browser. Same for the versions popover
+and the freeze dialog — unit/coverage exists, a human click-through is
+still owed.
## GPU vs CPU: what actually runs where (as of 2026-07-26)
@@ -63,31 +58,24 @@ work. The GPUI desktop app sidesteps it entirely (native GPU).
## Roadmap (priority order, owner's call)
-1. **Strip the landing page.** App should open straight into the editor /
- project list. The marketing front page is dead weight.
-2. **Strip upstream-branded links**: Discord link, "Send feedback" button.
-3. **Disable (or remove) sounds, stickers, effects** — unfinished or buggy
- upstream. Prefer disabling behind a flag/registry skip first; delete once
- proven unnecessary. Effects are GPU shader passes + a registry
- (`registerDefaultEffects`); stickers and sounds each live in their own
- domain folders, so excision is mechanically easy.
-4. **Project import/export as one self-contained file.** Project JSON +
- all media bundled in a single archive. Storage layer
- (`services/storage/`) already serializes projects (versioned migrations);
- media lives in IndexedDB as `File`s, so export = project JSON + media
- blobs into a zip; import = reverse through the same migration pipeline.
-5. **Voice-over recording.** `MediaRecorder` (mic) → audio `MediaAsset` →
- drop on timeline at playhead. The audio pipeline (assets, tracks,
- waveform) already exists; this is mostly UI + recording plumbing.
-6. **Git-like project versioning.** Named snapshots + history per project.
- The save manager and versioned storage are the natural foundation;
- snapshot blobs could reuse the export format from (4). Hardest and most
- novel item — design note needed before code.
+1. ~~Strip the landing page~~ done.
+2. ~~Strip upstream-branded links~~ done.
+3. ~~Disable sounds, stickers, effects~~ done behind `FEATURES` flags.
+ Next step here: actually DELETE the flagged-off domain code (and the
+ freesound API route, sticker providers, sounds panel internals) once the
+ flags have baked a while — that also kills a chunk of the ~112
+ pre-existing lint errors.
+4. ~~Project import/export as one self-contained file~~ done (`.ocp`).
+5. ~~Voice-over recording~~ done.
+6. ~~Git-like project versioning~~ done (v1). v2 candidates: diff view,
+ branches, content-addressed media dedup, shipping history inside `.ocp`.
7. **Self-contained binary, first-class Linux + BSD.** `apps/desktop` (GPUI)
is the vehicle but is a hello-world scaffold today; porting the editor is
a large effort. Caveat: GPUI's Linux support is young; BSD support is
unproven — spike before committing. Browser version stays regardless
- (editing in a browser is a feature, not a compromise).
+ (editing in a browser is a feature, not a compromise). Distribution:
+ AppImage/GitHub releases first; Flathub is effectively closed to us (June
+ 2026 policy bans AI-assisted code in new submissions).
## Deprioritized / parked