summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/controllers
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/timeline/controllers
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/timeline/controllers')
-rw-r--r--apps/web/src/timeline/controllers/resize-controller.ts37
1 files changed, 25 insertions, 12 deletions
diff --git a/apps/web/src/timeline/controllers/resize-controller.ts b/apps/web/src/timeline/controllers/resize-controller.ts
index a1098915..a657c695 100644
--- a/apps/web/src/timeline/controllers/resize-controller.ts
+++ b/apps/web/src/timeline/controllers/resize-controller.ts
@@ -109,18 +109,30 @@ export function buildResizeMembers({
? elementEnd
: maxMediaTime({ a: bound, b: elementEnd });
}, null);
- const rightNeighborBound = otherElements
- .filter(
- (el) =>
- el.startTime >= addMediaTime({ a: element.startTime, b: element.duration }),
- )
- .reduce<MediaTime | null>(
- (bound, el) =>
- bound === null
- ? el.startTime
- : minMediaTime({ a: bound, b: el.startTime }),
- null,
- );
+ const rightElements = otherElements.filter(
+ (el) =>
+ el.startTime >= addMediaTime({ a: element.startTime, b: element.duration }),
+ );
+ const rightNeighborBound = rightElements.reduce<MediaTime | null>(
+ (bound, el) =>
+ bound === null
+ ? el.startTime
+ : minMediaTime({ a: bound, b: el.startTime }),
+ null,
+ );
+ const rightPushChain =
+ element.sourceDuration == null
+ ? rightElements
+ .sort((a, b) => (a.startTime > b.startTime ? 1 : -1))
+ .map((el) => ({
+ trackId,
+ elementId: el.id,
+ startTime: el.startTime,
+ duration: el.duration,
+ trimStart: el.trimStart,
+ trimEnd: el.trimEnd,
+ }))
+ : undefined;
return [
{
@@ -134,6 +146,7 @@ export function buildResizeMembers({
retime: isRetimableElement(element) ? element.retime : undefined,
leftNeighborBound,
rightNeighborBound,
+ rightPushChain,
},
];
});