fix(core): remove 1800s hard cap on timeline duration that silently truncated long compositions (#1114)

The runtime had a maxTimelineDurationSeconds field defaulting to 1800
(30 minutes) that clamped the TransportClock duration. Any seek beyond
this cap was silently clamped, so GSAP tweens starting past ~1700s
never received their totalTime() call and stayed at their pre-tween
state (e.g. opacity:0).

The data-duration attribute is the authored source of truth. The loop-
inflation guard (timelineLooksLoopInflated) already handles the infinite
repeat:-1 case this cap was meant to protect against.

Closes #1107
This commit is contained in:
Miguel Ángel
2026-05-28 16:26:40 -04:00
committed by GitHub
parent 5245e19062
commit e0cb8fcee3
5 changed files with 7 additions and 25 deletions
+2 -12
View File
@@ -176,7 +176,6 @@ function buildTimelineClipLabel(node: Element, kind: RuntimeTimelineClip["kind"]
export function collectRuntimeTimelinePayload(params: {
canonicalFps: number;
maxTimelineDurationSeconds: number;
}): RuntimeTimelineMessage {
const runtimeWindow = window as Window & {
__timelines?: Record<string, RuntimeTimelineLike | undefined>;
@@ -347,10 +346,7 @@ export function collectRuntimeTimelinePayload(params: {
mediaWindowDurationCandidate,
compositionWindowDurationCandidate,
));
const rootCompositionDuration =
preferredRootDuration != null
? Math.min(preferredRootDuration, params.maxTimelineDurationSeconds)
: null;
const rootCompositionDuration = preferredRootDuration ?? null;
const rootCompositionEnd =
rootCompositionDuration != null ? rootCompositionStart + rootCompositionDuration : null;
const timelineWindowEnd =
@@ -666,13 +662,7 @@ export function collectRuntimeTimelinePayload(params: {
// hide structural/background tracks from the timeline UI; if we collapse the
// payload duration down to the last visible clip end, the controls jump even
// though playback still runs for the full authored root duration.
const safeDuration = Math.max(
1,
Math.min(
Math.max(maxEnd || 1, rootCompositionDuration ?? 0),
params.maxTimelineDurationSeconds,
),
);
const safeDuration = Math.max(1, maxEnd || 1, rootCompositionDuration ?? 0);
const shouldEmitNonDeterministicInf = timelineLooksLoopInflated && attrDurationCandidate == null;
const durationInFrames = shouldEmitNonDeterministicInf
? Number.POSITIVE_INFINITY