From ba5e37ea88a034af9a2c6e42a601e2ac86b1f6e8 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Sat, 3 Oct 2026 22:23:34 +0300 Subject: [PATCH] feat(ui): preview plays the cut clip to clip on the playhead clock, with scrubber, stop/play, timecode and Save frame Co-Authored-By: Claude Sonnet 5.5 --- app/ui/composer/elements/gallery.js | 6 +- app/ui/features/placeholders/index.js | 7 -- app/ui/features/preview/index.js | 103 ++++++++++++++++++++----- app/ui/features/preview/player.test.js | 16 ++++ 4 files changed, 105 insertions(+), 27 deletions(-) create mode 100644 app/ui/features/preview/player.test.js diff --git a/app/ui/composer/elements/gallery.js b/app/ui/composer/elements/gallery.js index 0074db41..2fa17119 100644 --- a/app/ui/composer/elements/gallery.js +++ b/app/ui/composer/elements/gallery.js @@ -277,7 +277,7 @@ define("ruler", "default", ({ marks = [], total = 1, label } = {}) => { * load" have to look different, and a bare with a broken src looks like * neither. */ -define("viewer", "media", ({ src, kind = "image", empty = "Nothing yet", onError } = {}) => { +define("viewer", "media", ({ src, kind = "image", empty = "Nothing yet", onError, controls = true, loop = true } = {}) => { const stage = el("div", { cls: "cx-viewer-stage" }); let current = null; let currentKind = kind; @@ -295,7 +295,7 @@ define("viewer", "media", ({ src, kind = "image", empty = "Nothing yet", onError return; } const media = nextKind === "video" - ? el("video", { cls: "cx-viewer-media", attrs: { src: current, controls: "", loop: "", playsinline: "" } }) + ? el("video", { cls: "cx-viewer-media", attrs: { src: current, controls: controls ? "" : undefined, loop: loop ? "" : undefined, playsinline: "" } }) : el("img", { cls: "cx-viewer-media", attrs: { src: current, alt: "" } }); mediaEl = media; // A failed load is reported rather than left as a broken icon: the file is @@ -322,6 +322,8 @@ define("viewer", "media", ({ src, kind = "image", empty = "Nothing yet", onError // caller had one to give. Null for anything shown by URL alone, which is // not enough to name a file back to the server with. get file() { return currentFile; }, + /** The