@linker-design-plus/timeline-track 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
- import type { ActiveClipPlaybackInfo, ClipVisualTransform, PlayState, PreviewAspectRatio, TimeMs, TrackType } from '../models/types';
2
- import type { PreviewPendingState } from './previewBackend';
1
+ import type { ActiveClipPlaybackInfo, ClipVisualTransform, PlayState, PreviewAspectRatio, PreviewSourceResolver, TimeMs, TrackType } from '../models/types';
2
+ import type { PreviewPendingState, PreviewRuntimeState } from './previewBackend';
3
3
  interface TimelinePreviewSessionCallbacks {
4
4
  onBufferingStateChange?: (isBuffering: boolean) => void;
5
5
  onSourceLoadingChange?: (pending: number) => void;
6
6
  onSyncProcessed?: (syncRequestId?: number) => void;
7
+ onRuntimeStateChange?: (state: PreviewRuntimeState) => void;
7
8
  onAspectRatioChange?: (aspectRatio: PreviewAspectRatio) => void;
8
9
  onVisualTransformCommit?: (clipId: string, visualTransform: ClipVisualTransform) => void;
9
10
  onPendingPreviewRetry?: () => void;
@@ -15,6 +16,7 @@ interface TimelinePreviewSessionDependencies {
15
16
  rootClassName?: string;
16
17
  frameClassName?: string;
17
18
  slotClassNamePrefix?: string;
19
+ previewSourceResolver?: PreviewSourceResolver;
18
20
  }
19
21
  export interface TimelinePreviewSyncPayload {
20
22
  activeClips: ActiveClipPlaybackInfo[];
@@ -24,7 +26,7 @@ export interface TimelinePreviewSyncPayload {
24
26
  currentTime: TimeMs;
25
27
  playState: PlayState;
26
28
  speed: number;
27
- selectedClipId?: string | null;
29
+ primarySelectedClipId?: string | null;
28
30
  syncRequestId?: number;
29
31
  }
30
32
  export declare class TimelinePreviewSession {
@@ -39,9 +41,13 @@ export declare class TimelinePreviewSession {
39
41
  private readonly trackSlots;
40
42
  private audioContext;
41
43
  private masterGainNode;
42
- private isBuffering;
43
44
  private loadingCount;
44
- private selectedClipId;
45
+ private isBuffering;
46
+ private bufferingVisibleTimeoutId;
47
+ private lastRuntimeSignature;
48
+ private lastRuntimeState;
49
+ private lastSettledSyncRequestId;
50
+ private primarySelectedClipId;
45
51
  private transientVisualTransform;
46
52
  private readonly callbacks;
47
53
  private readonly dependencies;
@@ -50,9 +56,14 @@ export declare class TimelinePreviewSession {
50
56
  private resolvedAutoAspectRatio;
51
57
  private aspectRatioProbe;
52
58
  private aspectRatioProbeSrc;
59
+ private aspectRatioProbeResolveToken;
53
60
  private isAspectRatioProbeLoading;
54
61
  private pendingState;
62
+ private activeSyncRequestId;
63
+ private isSyncProjecting;
55
64
  constructor(callbacks?: TimelinePreviewSessionCallbacks, dependencies?: TimelinePreviewSessionDependencies);
65
+ private logLoadTrace;
66
+ private buildSlotTraceData;
56
67
  hasPreview(): boolean;
57
68
  attach(container: HTMLElement): void;
58
69
  detach(): void;
@@ -65,7 +76,15 @@ export declare class TimelinePreviewSession {
65
76
  private destroySlot;
66
77
  private getTrackSlots;
67
78
  private swapTrackSlots;
68
- private assignClipToSlot;
79
+ private applyTrackPlan;
80
+ private applySlotTarget;
81
+ private resolveDesiredSource;
82
+ private slotNeedsRecovery;
83
+ private recoverSlot;
84
+ private finishSlotRecovery;
85
+ private applyResolvedSlotState;
86
+ private isCurrentRequest;
87
+ private failSlot;
69
88
  private configureAudioRouting;
70
89
  private syncCurrentSlot;
71
90
  private preparePreloadSlot;
@@ -75,13 +94,13 @@ export declare class TimelinePreviewSession {
75
94
  private resumeAudioContext;
76
95
  private updateFrameLayout;
77
96
  private maybeResolveAutoAspectRatio;
97
+ private resolveAspectRatioProbeSource;
78
98
  private getAspectRatioProbe;
79
99
  private tryResolveAutoAspectRatioFromSlot;
80
100
  private handleResolvedAutoAspectRatio;
81
- private refreshBufferingState;
82
- private setBufferingState;
83
- private refreshLoadingState;
84
- private setLoadingCount;
101
+ private refreshRuntimeState;
102
+ private syncVisibleBufferingState;
103
+ private clearBufferingVisibleTimeout;
85
104
  private refreshPendingOverlay;
86
105
  private handlePreviewTransformChange;
87
106
  private refreshVisualLayout;
@@ -0,0 +1,53 @@
1
+ import type { TimeMs } from '../models/types';
2
+ import type { PreviewPendingState, PreviewRuntimeState } from './previewBackend';
3
+ export interface TimelinePendingPreviewState {
4
+ mode: 'seek' | 'scrub';
5
+ targetTime: TimeMs;
6
+ resumePlayOnReady: boolean;
7
+ errorMessage: string | null;
8
+ timeoutId: ReturnType<typeof setTimeout> | null;
9
+ awaitingSync: boolean;
10
+ syncRequestId: number;
11
+ }
12
+ interface TimelinePreviewStateControllerCallbacks {
13
+ applyPendingState: (state: PreviewPendingState | null) => void;
14
+ emitBufferingStateChange: (isBuffering: boolean) => void;
15
+ emitSourceLoadingStateChange: () => void;
16
+ resumePlayback: () => void;
17
+ requestPreviewSync: () => void;
18
+ }
19
+ interface TimelinePreviewStateControllerOptions {
20
+ callbacks: TimelinePreviewStateControllerCallbacks;
21
+ pendingTimeoutMs?: number;
22
+ }
23
+ export declare class TimelinePreviewStateController {
24
+ private readonly callbacks;
25
+ private readonly pendingTimeoutMs;
26
+ private _previewSourceLoadingCount;
27
+ private _previewBuffering;
28
+ private _previewAwaitingMedia;
29
+ private _pendingPreviewState;
30
+ private _nextPendingPreviewSyncRequestId;
31
+ constructor(options: TimelinePreviewStateControllerOptions);
32
+ get previewSourceLoadingCount(): number;
33
+ set previewSourceLoadingCount(value: number);
34
+ get previewBuffering(): boolean;
35
+ set previewBuffering(value: boolean);
36
+ get pendingPreviewState(): TimelinePendingPreviewState | null;
37
+ set pendingPreviewState(value: TimelinePendingPreviewState | null);
38
+ get nextPendingPreviewSyncRequestId(): number;
39
+ set nextPendingPreviewSyncRequestId(value: number);
40
+ handleBufferingStateChange(isBuffering: boolean): void;
41
+ handleSourceLoadingChange(pending: number): void;
42
+ handleRuntimeStateChange(state: PreviewRuntimeState): void;
43
+ markSyncProcessed(syncRequestId?: number): void;
44
+ beginPendingPreview(time: TimeMs, mode: 'seek' | 'scrub', resumePlayOnReady: boolean): void;
45
+ buildPreviewPendingState(): PreviewPendingState | null;
46
+ updatePendingPreviewState(): void;
47
+ retryPendingPreview(): void;
48
+ clearPendingPreviewState(): void;
49
+ resetPreviewRuntimeState(): void;
50
+ private ensurePendingPreviewTimeout;
51
+ private clearPendingPreviewTimeout;
52
+ }
53
+ export {};
@@ -4,7 +4,7 @@ export interface SelectedClipSnapshot {
4
4
  hasSelectedClip: boolean;
5
5
  }
6
6
  interface ResolveSelectedClipOptions {
7
- getSelectedClip: () => Clip | null;
7
+ getPrimarySelectedClip: () => Clip | null;
8
8
  findFallbackSelectedClip?: () => Clip | null;
9
9
  }
10
10
  interface EmitSelectedClipChangeOptions {
@@ -1,3 +1,4 @@
1
+ import { type TimelinePreviewBackend } from '../controllers';
1
2
  import { TimelineConfig, Clip, ClipConfig, TimeMs, PlayState, Action, TimelineEvent, EventListener as TimelineEventListener, TimelineExportData, ThumbnailProvider, TrackInsertionPlacement, TrackType, ActiveClipPlaybackInfo, PreviewAspectRatio, PreviewMountConfig, PreviewBackendType } from '../models';
2
3
  import type { ResolvedPlaybackPlan } from '../controllers/timelinePlaybackResolver';
3
4
  import { TimelineClipConfigController } from '../controllers/timelineClipConfigController';
@@ -48,16 +49,12 @@ export declare class TimelineManager {
48
49
  private timelinePresentationAdapter?;
49
50
  private timelineTrackBridge?;
50
51
  private timelinePlaybackResolver?;
51
- private previewSession?;
52
- private previewMountContainer;
53
- private resolvedPreviewBackend;
54
- private runtimePreviewBackendOverride;
52
+ private previewRuntimeController?;
53
+ private previewStateController?;
54
+ private previewPlaybackSuspendedByBuffering;
55
+ private previewPlaybackAutoResume;
56
+ private previewBufferingSuspendTimeoutId;
55
57
  private lastSelectedClipId;
56
- private previewSourceLoadingCount;
57
- private previewBuffering;
58
- private pendingPreviewState;
59
- private nextPendingPreviewSyncRequestId;
60
- private activePreviewCallbackToken;
61
58
  private previewAspectRatio;
62
59
  private readonly bodyViewportScrollListener;
63
60
  private readonly bodyCanvasHostClickListener;
@@ -74,11 +71,29 @@ export declare class TimelineManager {
74
71
  private getTimelinePresentationAdapter;
75
72
  private getTimelineTrackBridge;
76
73
  private getTimelinePlaybackResolver;
74
+ get previewSession(): TimelinePreviewBackend | undefined;
75
+ set previewSession(value: TimelinePreviewBackend | undefined);
76
+ get previewMountContainer(): HTMLElement | null;
77
+ set previewMountContainer(value: HTMLElement | null);
78
+ get resolvedPreviewBackend(): Exclude<PreviewBackendType, 'auto'>;
79
+ set resolvedPreviewBackend(value: Exclude<PreviewBackendType, 'auto'>);
80
+ get runtimePreviewBackendOverride(): Exclude<PreviewBackendType, 'auto'> | null;
81
+ set runtimePreviewBackendOverride(value: Exclude<PreviewBackendType, 'auto'> | null);
82
+ get activePreviewCallbackToken(): number;
83
+ set activePreviewCallbackToken(value: number);
84
+ private get previewSourceLoadingCount();
85
+ private set previewSourceLoadingCount(value);
86
+ get previewBuffering(): boolean;
87
+ set previewBuffering(value: boolean);
88
+ private get pendingPreviewState();
89
+ private set pendingPreviewState(value);
90
+ get nextPendingPreviewSyncRequestId(): number;
91
+ set nextPendingPreviewSyncRequestId(value: number);
92
+ private getPreviewStateController;
93
+ private getPreviewRuntimeController;
77
94
  private resolveConfiguredPreviewBackend;
78
95
  private createPreviewBackendCallbacks;
79
- private createPreviewBackend;
80
96
  private isActivePreviewCallbackToken;
81
- private getPreviewSession;
82
97
  private getEventDispatcher;
83
98
  private getDefaultTrackForHistory;
84
99
  private getTimelineHistoryRecorder;
@@ -121,14 +136,11 @@ export declare class TimelineManager {
121
136
  private registerPreviewAutoAspectRatioClip;
122
137
  private syncPreviewSession;
123
138
  private beginPendingPreview;
124
- private updatePendingPreviewState;
139
+ updatePendingPreviewState(): void;
125
140
  private buildPreviewPendingState;
126
- private ensurePendingPreviewTimeout;
127
- private clearPendingPreviewTimeout;
128
141
  private clearPendingPreviewState;
129
142
  private resetPreviewRuntimeState;
130
143
  private destroyPreviewSession;
131
- private recreateDetachedPreviewSession;
132
144
  private retryPendingPreview;
133
145
  private handlePreviewBackendRuntimeError;
134
146
  init(container: HTMLElement): void;
@@ -172,6 +184,8 @@ export declare class TimelineManager {
172
184
  pause(): void;
173
185
  togglePlay(): void;
174
186
  private animate;
187
+ private syncPlaybackClockToPreviewBuffering;
188
+ private clearPreviewBufferingSuspendTimeout;
175
189
  setCurrentTime(time: TimeMs): void;
176
190
  getCurrentTime(): TimeMs;
177
191
  setEnableClipSnap(enabled: boolean): void;
@@ -256,6 +270,7 @@ export declare class TimelineManager {
256
270
  private getExportComposition;
257
271
  exportTimeline(): TimelineExportData;
258
272
  importTimeline(data: TimelineExportData): Promise<void>;
273
+ private stopPlaybackForImport;
259
274
  getClipsData(): Clip[];
260
275
  /**
261
276
  * 获取插件版本号
@@ -320,12 +335,18 @@ export declare class TimelineManager {
320
335
  */
321
336
  private notifySelectionChange;
322
337
  private syncPrimarySelectionFromSelectionStore;
338
+ private getOrderedSelectionClipIds;
339
+ setSelection(clipIds: string[], options?: {
340
+ preferredPrimaryClipId?: string | null;
341
+ selectedClipEventClip?: Clip | null;
342
+ }): void;
323
343
  selectClip(clipId: string, clip?: any): void;
324
344
  /**
325
345
  * 清空所有轨道的选中状态
326
346
  */
327
347
  clearSelection(): void;
328
348
  getSelectedClipIds(): string[];
349
+ getPrimarySelectedClipId(): string | null;
329
350
  addToSelection(clipId: string): void;
330
351
  removeFromSelection(clipId: string): void;
331
352
  toggleSelection(clipId: string): void;
@@ -334,7 +355,6 @@ export declare class TimelineManager {
334
355
  separateSelectedClipsAudio(): void;
335
356
  selectAllClips(): void;
336
357
  private emitSelectionChangeEvent;
337
- private updateAllTracksSelectionVisual;
338
358
  /**
339
359
  * 滚动到指定片段
340
360
  * @param clipId 目标片段的 ID
@@ -353,6 +373,7 @@ export declare class TimelineManager {
353
373
  * @returns 当前选中的 clip,如果没有则返回 null
354
374
  */
355
375
  getSelectedClip(): Clip | null;
376
+ getPrimarySelectedClip(): Clip | null;
356
377
  getSelectedClips(): Clip[];
357
378
  canDeleteSelectedClips(): boolean;
358
379
  getSelectedClipAudioAction(): 'separate' | 'restore' | null;
@@ -366,6 +387,7 @@ export declare class TimelineManager {
366
387
  detachPreview(): void;
367
388
  attachClipConfig(container: HTMLElement): TimelineClipConfigController;
368
389
  getPreviewBackendType(): Exclude<PreviewBackendType, 'auto'>;
390
+ hasAttachedPreview(): boolean;
369
391
  getPreviewAspectRatio(): PreviewAspectRatio;
370
392
  setPreviewAspectRatio(aspectRatio: {
371
393
  width: number;
@@ -20,7 +20,7 @@ export interface ClipVisualTransform {
20
20
  y: number;
21
21
  scale: number;
22
22
  }
23
- export type PreviewBackendType = 'dom' | 'canvas' | 'pixi' | 'auto';
23
+ export type PreviewBackendType = 'dom' | 'canvas' | 'auto';
24
24
  export interface Mp4PreviewMediaSource {
25
25
  url: string;
26
26
  mimeType: string;
@@ -17,6 +17,6 @@ export declare class TimelinePresentationAdapter {
17
17
  syncZoom(timeline: TimelineZoomView | null, playhead: TimelineZoomView | null, tracks: TimelineTrackCollection, zoom: number): void;
18
18
  syncScrollLeft(playhead: TimelineScrollView | null, tracks: TimelineTrackCollection, scrollLeft: number): void;
19
19
  syncScrollTop(panel: TimelineVerticalScrollView | null, scrollbar: TimelineVerticalScrollView | null, scrollTop: number): void;
20
- syncSelection(tracks: TimelineTrackCollection, selectedClipId: string | null, selectedClipIds?: string[]): void;
20
+ syncSelection(tracks: TimelineTrackCollection, selectedClipIds: string[]): void;
21
21
  findSelectedClip(tracks: TimelineTrackCollection): Clip | null;
22
22
  }
@@ -1,11 +1,13 @@
1
1
  export declare class SelectionStore {
2
2
  private selectedClipIds;
3
+ getPrimarySelectedClipId(): string | null;
3
4
  getSelectedClipId(): string | null;
4
5
  getSelectedClipIds(): string[];
5
6
  addToSelection(clipId: string): void;
6
7
  removeFromSelection(clipId: string): void;
7
8
  toggleSelection(clipId: string): void;
8
9
  setSelection(clipIds: string[]): void;
10
+ setPrimarySelection(clipId: string | null): void;
9
11
  setSelectedClipId(clipId: string | null): void;
10
12
  clear(): void;
11
13
  hasSelection(): boolean;
@@ -11,13 +11,18 @@ export interface TimelineStoreInitialState {
11
11
  viewportHeight?: number;
12
12
  contentHeight?: number;
13
13
  selectedClipId?: string | null;
14
+ selectedClipIds?: string[];
14
15
  }
15
16
  export declare class TimelineStore {
16
17
  private readonly selectionStore;
17
18
  private readonly playbackStore;
18
19
  private readonly viewportStore;
19
20
  constructor(initial: TimelineStoreInitialState);
21
+ getPrimarySelectedClipId(): string | null;
20
22
  getSelectedClipId(): string | null;
23
+ getSelectedClipIds(): string[];
24
+ setSelectedClipIds(clipIds: string[]): void;
25
+ setPrimarySelectedClipId(clipId: string | null): void;
21
26
  setSelectedClipId(clipId: string | null): void;
22
27
  clearSelection(): void;
23
28
  hasSelection(): boolean;
@@ -13,10 +13,9 @@ export interface TimelineTrackCollectionItem extends TimelineTrackView {
13
13
  updateClip?(clipId: string, updates: Partial<Clip>): void;
14
14
  updateClipPosition?(clipId: string, newStartTime: TimeMs, isFinal: boolean, previewOffsetY?: number): void;
15
15
  removeClipGaps?(): void;
16
- updateSelectionVisual?(selectedClipId: string | null): void;
16
+ setSelection?(clipIds: string[], preferredClipId?: string | null): void;
17
17
  clearSelection?(): void;
18
- getSelectedClip?(): Clip | null;
19
- selectClip?(clipId: string): void;
18
+ getPrimarySelectedClip?(): Clip | null;
20
19
  setTrackY?(y: number): void;
21
20
  setTrackStackOrder?(order: number): void;
22
21
  setTrackHeight?(height: number): void;
@@ -26,7 +25,6 @@ export interface TimelineTrackCollectionItem extends TimelineTrackView {
26
25
  getTrackGroup?(): {
27
26
  destroy(): void;
28
27
  };
29
- updateClipSelection?(clipId: string, isSelected: boolean): void;
30
28
  }
31
29
  export declare class TimelineTrackCollection {
32
30
  private readonly tracks;
@@ -52,6 +50,8 @@ export declare class TimelineTrackCollection {
52
50
  moveClipToTrack(clip: Clip, sourceTrackId: string, targetTrackId: string): boolean;
53
51
  removeClipGaps(): void;
54
52
  clearSelection(): void;
53
+ syncSelection(clipIds: string[], preferredClipId?: string | null): void;
54
+ findPrimarySelectedClip(): Clip | null;
55
55
  forEach(callback: (track: TimelineTrackCollectionItem) => void): void;
56
56
  private findIndexById;
57
57
  private resolveTrackId;
@@ -14,6 +14,7 @@ export declare class TrackManager {
14
14
  private insertTrack;
15
15
  muteTrack(trackId: string, isMuted: boolean): boolean;
16
16
  isTrackMuted(trackId: string): boolean;
17
+ clearAllTracks(): void;
17
18
  getTrackCount(): number;
18
19
  getTrackCountByType(type: TrackType): number;
19
20
  }