@editframe/elements 0.20.4-beta.0 → 0.23.6-beta.0
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.
- package/dist/DelayedLoadingState.js +0 -27
- package/dist/EF_FRAMEGEN.d.ts +5 -3
- package/dist/EF_FRAMEGEN.js +49 -11
- package/dist/_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js +7 -0
- package/dist/attachContextRoot.d.ts +1 -0
- package/dist/attachContextRoot.js +9 -0
- package/dist/elements/ContextProxiesController.d.ts +1 -2
- package/dist/elements/EFAudio.js +5 -9
- package/dist/elements/EFCaptions.d.ts +1 -3
- package/dist/elements/EFCaptions.js +112 -129
- package/dist/elements/EFImage.js +6 -7
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +2 -5
- package/dist/elements/EFMedia/AssetMediaEngine.js +36 -33
- package/dist/elements/EFMedia/BaseMediaEngine.js +57 -73
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +1 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.js +134 -78
- package/dist/elements/EFMedia/JitMediaEngine.js +9 -19
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +7 -13
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +2 -3
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +6 -5
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +1 -3
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +1 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +9 -25
- package/dist/elements/EFMedia/shared/BufferUtils.js +2 -17
- package/dist/elements/EFMedia/shared/GlobalInputCache.js +0 -24
- package/dist/elements/EFMedia/shared/PrecisionUtils.js +0 -21
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +0 -17
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +1 -10
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.d.ts +29 -0
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +32 -0
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +1 -15
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +1 -7
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +8 -5
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +12 -13
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +1 -1
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +134 -70
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +11 -18
- package/dist/elements/EFMedia.d.ts +19 -0
- package/dist/elements/EFMedia.js +44 -25
- package/dist/elements/EFSourceMixin.js +5 -7
- package/dist/elements/EFSurface.js +6 -9
- package/dist/elements/EFTemporal.browsertest.d.ts +11 -0
- package/dist/elements/EFTemporal.d.ts +10 -0
- package/dist/elements/EFTemporal.js +100 -41
- package/dist/elements/EFThumbnailStrip.js +23 -73
- package/dist/elements/EFTimegroup.browsertest.d.ts +3 -3
- package/dist/elements/EFTimegroup.d.ts +35 -14
- package/dist/elements/EFTimegroup.js +138 -181
- package/dist/elements/EFVideo.d.ts +16 -2
- package/dist/elements/EFVideo.js +156 -108
- package/dist/elements/EFWaveform.js +23 -40
- package/dist/elements/SampleBuffer.js +3 -7
- package/dist/elements/TargetController.js +5 -5
- package/dist/elements/durationConverter.js +4 -4
- package/dist/elements/renderTemporalAudio.d.ts +10 -0
- package/dist/elements/renderTemporalAudio.js +35 -0
- package/dist/elements/updateAnimations.js +19 -43
- package/dist/gui/ContextMixin.d.ts +5 -5
- package/dist/gui/ContextMixin.js +167 -162
- package/dist/gui/Controllable.browsertest.d.ts +0 -0
- package/dist/gui/Controllable.d.ts +15 -0
- package/dist/gui/Controllable.js +9 -0
- package/dist/gui/EFConfiguration.js +7 -7
- package/dist/gui/EFControls.browsertest.d.ts +11 -0
- package/dist/gui/EFControls.d.ts +18 -4
- package/dist/gui/EFControls.js +70 -28
- package/dist/gui/EFDial.browsertest.d.ts +0 -0
- package/dist/gui/EFDial.d.ts +18 -0
- package/dist/gui/EFDial.js +141 -0
- package/dist/gui/EFFilmstrip.browsertest.d.ts +11 -0
- package/dist/gui/EFFilmstrip.d.ts +12 -2
- package/dist/gui/EFFilmstrip.js +214 -129
- package/dist/gui/EFFitScale.js +5 -8
- package/dist/gui/EFFocusOverlay.js +4 -4
- package/dist/gui/EFPause.browsertest.d.ts +0 -0
- package/dist/gui/EFPause.d.ts +23 -0
- package/dist/gui/EFPause.js +59 -0
- package/dist/gui/EFPlay.browsertest.d.ts +0 -0
- package/dist/gui/EFPlay.d.ts +23 -0
- package/dist/gui/EFPlay.js +59 -0
- package/dist/gui/EFPreview.d.ts +4 -0
- package/dist/gui/EFPreview.js +18 -9
- package/dist/gui/EFResizableBox.browsertest.d.ts +0 -0
- package/dist/gui/EFResizableBox.d.ts +34 -0
- package/dist/gui/EFResizableBox.js +547 -0
- package/dist/gui/EFScrubber.d.ts +9 -3
- package/dist/gui/EFScrubber.js +13 -13
- package/dist/gui/EFTimeDisplay.d.ts +7 -1
- package/dist/gui/EFTimeDisplay.js +8 -8
- package/dist/gui/EFToggleLoop.d.ts +9 -3
- package/dist/gui/EFToggleLoop.js +7 -5
- package/dist/gui/EFTogglePlay.d.ts +12 -4
- package/dist/gui/EFTogglePlay.js +26 -21
- package/dist/gui/EFWorkbench.js +5 -5
- package/dist/gui/PlaybackController.d.ts +67 -0
- package/dist/gui/PlaybackController.js +310 -0
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/TWMixin2.js +1 -1
- package/dist/gui/TargetOrContextMixin.d.ts +10 -0
- package/dist/gui/TargetOrContextMixin.js +98 -0
- package/dist/gui/efContext.d.ts +2 -2
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -1
- package/dist/otel/BridgeSpanExporter.d.ts +13 -0
- package/dist/otel/BridgeSpanExporter.js +87 -0
- package/dist/otel/setupBrowserTracing.d.ts +12 -0
- package/dist/otel/setupBrowserTracing.js +32 -0
- package/dist/otel/tracingHelpers.d.ts +34 -0
- package/dist/otel/tracingHelpers.js +112 -0
- package/dist/style.css +1 -1
- package/dist/transcoding/cache/RequestDeduplicator.js +0 -21
- package/dist/transcoding/cache/URLTokenDeduplicator.js +1 -21
- package/dist/transcoding/utils/UrlGenerator.js +2 -19
- package/dist/utils/LRUCache.js +6 -53
- package/package.json +13 -5
- package/src/elements/ContextProxiesController.ts +10 -10
- package/src/elements/EFAudio.ts +1 -0
- package/src/elements/EFCaptions.browsertest.ts +128 -56
- package/src/elements/EFCaptions.ts +60 -34
- package/src/elements/EFImage.browsertest.ts +1 -2
- package/src/elements/EFMedia/AssetMediaEngine.ts +65 -37
- package/src/elements/EFMedia/BaseMediaEngine.ts +110 -52
- package/src/elements/EFMedia/BufferedSeekingInput.ts +218 -101
- package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +3 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +7 -3
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +1 -1
- package/src/elements/EFMedia/videoTasks/MainVideoInputCache.ts +76 -0
- package/src/elements/EFMedia/videoTasks/makeScrubVideoInputTask.ts +16 -10
- package/src/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.ts +7 -1
- package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +222 -116
- package/src/elements/EFMedia.browsertest.ts +8 -15
- package/src/elements/EFMedia.ts +54 -8
- package/src/elements/EFSurface.browsertest.ts +2 -6
- package/src/elements/EFSurface.ts +1 -0
- package/src/elements/EFTemporal.browsertest.ts +58 -1
- package/src/elements/EFTemporal.ts +140 -4
- package/src/elements/EFThumbnailStrip.browsertest.ts +2 -8
- package/src/elements/EFThumbnailStrip.ts +1 -0
- package/src/elements/EFTimegroup.browsertest.ts +16 -15
- package/src/elements/EFTimegroup.ts +281 -275
- package/src/elements/EFVideo.browsertest.ts +162 -74
- package/src/elements/EFVideo.ts +229 -101
- package/src/elements/FetchContext.browsertest.ts +7 -2
- package/src/elements/TargetController.browsertest.ts +1 -0
- package/src/elements/TargetController.ts +1 -0
- package/src/elements/renderTemporalAudio.ts +108 -0
- package/src/elements/updateAnimations.browsertest.ts +181 -6
- package/src/elements/updateAnimations.ts +6 -6
- package/src/gui/ContextMixin.browsertest.ts +274 -27
- package/src/gui/ContextMixin.ts +230 -175
- package/src/gui/Controllable.browsertest.ts +258 -0
- package/src/gui/Controllable.ts +41 -0
- package/src/gui/EFControls.browsertest.ts +294 -80
- package/src/gui/EFControls.ts +139 -28
- package/src/gui/EFDial.browsertest.ts +84 -0
- package/src/gui/EFDial.ts +172 -0
- package/src/gui/EFFilmstrip.browsertest.ts +712 -0
- package/src/gui/EFFilmstrip.ts +213 -23
- package/src/gui/EFPause.browsertest.ts +202 -0
- package/src/gui/EFPause.ts +73 -0
- package/src/gui/EFPlay.browsertest.ts +202 -0
- package/src/gui/EFPlay.ts +73 -0
- package/src/gui/EFPreview.ts +20 -5
- package/src/gui/EFResizableBox.browsertest.ts +79 -0
- package/src/gui/EFResizableBox.ts +898 -0
- package/src/gui/EFScrubber.ts +7 -5
- package/src/gui/EFTimeDisplay.browsertest.ts +19 -19
- package/src/gui/EFTimeDisplay.ts +3 -1
- package/src/gui/EFToggleLoop.ts +6 -5
- package/src/gui/EFTogglePlay.ts +30 -23
- package/src/gui/PlaybackController.ts +522 -0
- package/src/gui/TWMixin.css +3 -0
- package/src/gui/TargetOrContextMixin.ts +185 -0
- package/src/gui/efContext.ts +2 -2
- package/src/otel/BridgeSpanExporter.ts +150 -0
- package/src/otel/setupBrowserTracing.ts +73 -0
- package/src/otel/tracingHelpers.ts +251 -0
- package/test/cache-integration-verification.browsertest.ts +1 -1
- package/types.json +1 -1
- package/dist/elements/ContextProxiesController.js +0 -69
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { LitElement } from "lit";
|
|
2
2
|
import { customElement } from "lit/decorators/custom-element.js";
|
|
3
|
-
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { describe, expect, test, vi } from "vitest";
|
|
4
4
|
import { EFTemporal } from "./EFTemporal.js";
|
|
5
|
+
import "./EFTimegroup.js";
|
|
6
|
+
import { state } from "lit/decorators.js";
|
|
5
7
|
|
|
6
8
|
@customElement("ten-seconds")
|
|
7
9
|
class TenSeconds extends EFTemporal(LitElement) {
|
|
@@ -156,3 +158,58 @@ describe("EFVideo sourcein attribute", () => {
|
|
|
156
158
|
expect(element2.tagName).toBe("EF-VIDEO");
|
|
157
159
|
});
|
|
158
160
|
});
|
|
161
|
+
|
|
162
|
+
@customElement("test-root-lifecycle")
|
|
163
|
+
class TestLifecycleChild extends EFTemporal(LitElement) {
|
|
164
|
+
@state()
|
|
165
|
+
role: "root" | "child" | null = null;
|
|
166
|
+
|
|
167
|
+
didBecomeRoot() {
|
|
168
|
+
this.role = "root";
|
|
169
|
+
}
|
|
170
|
+
didBecomeChild() {
|
|
171
|
+
this.role = "child";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
declare global {
|
|
176
|
+
interface HTMLElementTagNameMap {
|
|
177
|
+
"test-root-lifecycle": TestLifecycleChild;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
describe("Temporal Lifecycle", () => {
|
|
182
|
+
test("a standalone temporal element becomes a root", async () => {
|
|
183
|
+
const root = document.createElement("test-root-lifecycle");
|
|
184
|
+
document.body.append(root);
|
|
185
|
+
expect(root.role).toBe("root");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("temporal element in a timegroup becomes a child", async () => {
|
|
189
|
+
const timegroup = document.createElement("ef-timegroup");
|
|
190
|
+
vi.spyOn(timegroup as any, "didBecomeRoot");
|
|
191
|
+
vi.spyOn(timegroup as any, "didBecomeChild");
|
|
192
|
+
const child = document.createElement("test-root-lifecycle");
|
|
193
|
+
vi.spyOn(child as any, "didBecomeRoot");
|
|
194
|
+
vi.spyOn(child as any, "didBecomeChild");
|
|
195
|
+
timegroup.append(child);
|
|
196
|
+
document.body.append(timegroup);
|
|
197
|
+
expect((timegroup as any).didBecomeRoot).toHaveBeenCalledOnce();
|
|
198
|
+
expect((timegroup as any).didBecomeChild).not.toHaveBeenCalled();
|
|
199
|
+
expect((child as any).didBecomeChild).toHaveBeenCalledOnce();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("timegroup nested in a timegroup becomes a child", async () => {
|
|
203
|
+
const timegroup = document.createElement("ef-timegroup");
|
|
204
|
+
const child = document.createElement("ef-timegroup");
|
|
205
|
+
vi.spyOn(timegroup as any, "didBecomeRoot");
|
|
206
|
+
vi.spyOn(timegroup as any, "didBecomeChild");
|
|
207
|
+
vi.spyOn(child as any, "didBecomeRoot");
|
|
208
|
+
vi.spyOn(child as any, "didBecomeChild");
|
|
209
|
+
timegroup.append(child);
|
|
210
|
+
document.body.append(timegroup);
|
|
211
|
+
expect((timegroup as any).didBecomeRoot).toHaveBeenCalledOnce();
|
|
212
|
+
expect((timegroup as any).didBecomeChild).not.toHaveBeenCalled();
|
|
213
|
+
expect((child as any).didBecomeChild).toHaveBeenCalledOnce();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -3,6 +3,7 @@ import { Task } from "@lit/task";
|
|
|
3
3
|
import type { LitElement, ReactiveController } from "lit";
|
|
4
4
|
import { property, state } from "lit/decorators.js";
|
|
5
5
|
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
6
|
+
import { PlaybackController } from "../gui/PlaybackController.js";
|
|
6
7
|
import { durationConverter } from "./durationConverter.js";
|
|
7
8
|
import type { EFTimegroup } from "./EFTimegroup.js";
|
|
8
9
|
|
|
@@ -11,6 +12,12 @@ export const timegroupContext = createContext<EFTimegroup>(
|
|
|
11
12
|
);
|
|
12
13
|
|
|
13
14
|
export declare class TemporalMixinInterface {
|
|
15
|
+
playbackController?: PlaybackController;
|
|
16
|
+
playing: boolean;
|
|
17
|
+
loop: boolean;
|
|
18
|
+
play(): void;
|
|
19
|
+
pause(): void;
|
|
20
|
+
|
|
14
21
|
get hasOwnDuration(): boolean;
|
|
15
22
|
/**
|
|
16
23
|
* Whether the element has a duration set as an attribute.
|
|
@@ -156,6 +163,7 @@ export declare class TemporalMixinInterface {
|
|
|
156
163
|
* For other temporal elements: their ownCurrentTimeMs
|
|
157
164
|
*/
|
|
158
165
|
get currentTimeMs(): number;
|
|
166
|
+
set currentTimeMs(value: number);
|
|
159
167
|
/**
|
|
160
168
|
* The current time of the element in milliseconds, adjusted for trimming.
|
|
161
169
|
*
|
|
@@ -209,6 +217,11 @@ export declare class TemporalMixinInterface {
|
|
|
209
217
|
rootTimegroup?: EFTimegroup;
|
|
210
218
|
|
|
211
219
|
frameTask: Task<readonly unknown[], unknown>;
|
|
220
|
+
|
|
221
|
+
didBecomeRoot(): void;
|
|
222
|
+
didBecomeChild(): void;
|
|
223
|
+
|
|
224
|
+
updateComplete: Promise<boolean>;
|
|
212
225
|
}
|
|
213
226
|
|
|
214
227
|
export const isEFTemporal = (obj: any): obj is TemporalMixinInterface =>
|
|
@@ -310,9 +323,10 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
310
323
|
|
|
311
324
|
#parentTimegroup?: EFTimegroup;
|
|
312
325
|
@consume({ context: timegroupContext, subscribe: true })
|
|
313
|
-
@property({ attribute: false })
|
|
314
326
|
set parentTimegroup(value: EFTimegroup | undefined) {
|
|
327
|
+
const oldParent = this.#parentTimegroup;
|
|
315
328
|
this.#parentTimegroup = value;
|
|
329
|
+
|
|
316
330
|
this.ownCurrentTimeController?.remove();
|
|
317
331
|
this.rootTimegroup = this.getRootTimegroup();
|
|
318
332
|
if (this.rootTimegroup) {
|
|
@@ -321,17 +335,87 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
321
335
|
this as InstanceType<Constructor<TemporalMixinInterface> & T>,
|
|
322
336
|
);
|
|
323
337
|
}
|
|
338
|
+
|
|
339
|
+
// Only trigger callbacks if parent status actually changed
|
|
340
|
+
if (oldParent !== value) {
|
|
341
|
+
if (!value) {
|
|
342
|
+
this.didBecomeRoot();
|
|
343
|
+
} else {
|
|
344
|
+
this.didBecomeChild();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
324
347
|
}
|
|
325
348
|
|
|
326
349
|
disconnectedCallback() {
|
|
327
350
|
super.disconnectedCallback();
|
|
328
351
|
this.ownCurrentTimeController?.remove();
|
|
352
|
+
|
|
353
|
+
if (this.playbackController) {
|
|
354
|
+
this.playbackController.remove();
|
|
355
|
+
this.playbackController = undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
connectedCallback() {
|
|
360
|
+
super.connectedCallback();
|
|
361
|
+
// Initialize playback controller for root elements
|
|
362
|
+
// The parentTimegroup setter may have already called this, but the guard prevents double-creation
|
|
363
|
+
if (!this.parentTimegroup) {
|
|
364
|
+
this.didBecomeRoot();
|
|
365
|
+
}
|
|
329
366
|
}
|
|
330
367
|
|
|
331
368
|
get parentTimegroup() {
|
|
332
369
|
return this.#parentTimegroup;
|
|
333
370
|
}
|
|
334
371
|
|
|
372
|
+
playbackController?: PlaybackController;
|
|
373
|
+
|
|
374
|
+
get playing(): boolean {
|
|
375
|
+
if (!this.playbackController) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
return this.playbackController.playing;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
set playing(value: boolean) {
|
|
382
|
+
if (!this.playbackController) {
|
|
383
|
+
console.warn("Cannot set playing on non-root temporal element", this);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
this.playbackController.setPlaying(value);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
play(): void {
|
|
390
|
+
if (!this.playbackController) {
|
|
391
|
+
console.warn("play() called on non-root temporal element", this);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
this.playbackController.play();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
pause(): void {
|
|
398
|
+
if (!this.playbackController) {
|
|
399
|
+
console.warn("pause() called on non-root temporal element", this);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
this.playbackController.pause();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
@property({ type: Boolean, reflect: true, attribute: "loop" })
|
|
406
|
+
get loop(): boolean {
|
|
407
|
+
return this.playbackController?.loop ?? this.#loop;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
set loop(value: boolean) {
|
|
411
|
+
const oldValue = this.#loop;
|
|
412
|
+
this.#loop = value;
|
|
413
|
+
if (this.playbackController) {
|
|
414
|
+
this.playbackController.setLoop(value);
|
|
415
|
+
}
|
|
416
|
+
this.requestUpdate("loop", oldValue);
|
|
417
|
+
}
|
|
418
|
+
|
|
335
419
|
@property({
|
|
336
420
|
type: String,
|
|
337
421
|
attribute: "offset",
|
|
@@ -536,6 +620,8 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
536
620
|
return this.startTimeMs - this.parentTemporal.startTimeMs;
|
|
537
621
|
}
|
|
538
622
|
|
|
623
|
+
#loop = false;
|
|
624
|
+
|
|
539
625
|
get startTimeMs(): number {
|
|
540
626
|
const cachedStartTime = startTimeMsCache.get(this);
|
|
541
627
|
if (cachedStartTime !== undefined) {
|
|
@@ -596,18 +682,32 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
596
682
|
return this.startTimeMs + this.durationMs;
|
|
597
683
|
}
|
|
598
684
|
|
|
685
|
+
#currentTimeMs = 0;
|
|
686
|
+
|
|
599
687
|
/**
|
|
600
688
|
* The current time of the element within itself.
|
|
601
689
|
* Compare with `currentTimeMs` to see the current time with respect to the root timegroup
|
|
602
690
|
*/
|
|
603
|
-
get ownCurrentTimeMs() {
|
|
604
|
-
|
|
691
|
+
get ownCurrentTimeMs(): number {
|
|
692
|
+
// If we have a playback controller, read from it
|
|
693
|
+
if (this.playbackController) {
|
|
694
|
+
return Math.min(
|
|
695
|
+
Math.max(0, this.playbackController.currentTimeMs),
|
|
696
|
+
this.durationMs,
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (
|
|
701
|
+
this.rootTimegroup &&
|
|
702
|
+
this.rootTimegroup !== (this as any as EFTimegroup)
|
|
703
|
+
) {
|
|
605
704
|
return Math.min(
|
|
606
705
|
Math.max(0, this.rootTimegroup.currentTimeMs - this.startTimeMs),
|
|
607
706
|
this.durationMs,
|
|
608
707
|
);
|
|
609
708
|
}
|
|
610
|
-
|
|
709
|
+
// We are the root (or no root), use stored time
|
|
710
|
+
return Math.min(Math.max(0, this.#currentTimeMs), this.durationMs);
|
|
611
711
|
}
|
|
612
712
|
|
|
613
713
|
/**
|
|
@@ -618,6 +718,26 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
618
718
|
return this.ownCurrentTimeMs;
|
|
619
719
|
}
|
|
620
720
|
|
|
721
|
+
set currentTimeMs(value: number) {
|
|
722
|
+
// If we have a playback controller, delegate to it
|
|
723
|
+
if (this.playbackController) {
|
|
724
|
+
this.playbackController.currentTime = value / 1000;
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// If we have a root timegroup, delegate to it
|
|
729
|
+
if (
|
|
730
|
+
this.rootTimegroup &&
|
|
731
|
+
this.rootTimegroup !== (this as any as EFTimegroup)
|
|
732
|
+
) {
|
|
733
|
+
this.rootTimegroup.currentTimeMs = value;
|
|
734
|
+
} else {
|
|
735
|
+
// We are the root, store the time locally
|
|
736
|
+
this.#currentTimeMs = value;
|
|
737
|
+
this.requestUpdate("currentTimeMs");
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
621
741
|
/**
|
|
622
742
|
* Used to calculate the internal currentTimeMs of the element. This is useful
|
|
623
743
|
* for mapping to internal media time codes for audio/video elements.
|
|
@@ -637,6 +757,22 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
637
757
|
}
|
|
638
758
|
},
|
|
639
759
|
});
|
|
760
|
+
|
|
761
|
+
didBecomeRoot() {
|
|
762
|
+
if (!this.playbackController) {
|
|
763
|
+
this.playbackController = new PlaybackController(this as any);
|
|
764
|
+
if (this.#loop) {
|
|
765
|
+
this.playbackController.setLoop(this.#loop);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
didBecomeChild() {
|
|
771
|
+
if (this.playbackController) {
|
|
772
|
+
this.playbackController.remove();
|
|
773
|
+
this.playbackController = undefined;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
640
776
|
}
|
|
641
777
|
|
|
642
778
|
Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {
|
|
@@ -34,7 +34,7 @@ const test = baseTest.extend<{
|
|
|
34
34
|
const container = document.createElement("div");
|
|
35
35
|
render(
|
|
36
36
|
html`
|
|
37
|
-
<ef-configuration api-host="http://localhost:63315">
|
|
37
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
38
38
|
<div style="width: 600px; height: 400px;">
|
|
39
39
|
<ef-preview class="w-[600px] h-[300px]">
|
|
40
40
|
<ef-timegroup mode="contain" class="w-full h-full bg-black">
|
|
@@ -54,9 +54,6 @@ const test = baseTest.extend<{
|
|
|
54
54
|
);
|
|
55
55
|
document.body.appendChild(container);
|
|
56
56
|
|
|
57
|
-
const config = container.querySelector("ef-configuration") as any;
|
|
58
|
-
config.signingURL = "";
|
|
59
|
-
|
|
60
57
|
const timegroup = container.querySelector("ef-timegroup") as EFTimegroup;
|
|
61
58
|
const video = container.querySelector("ef-video") as EFVideo;
|
|
62
59
|
const thumbnailStrip = container.querySelector(
|
|
@@ -76,7 +73,7 @@ const test = baseTest.extend<{
|
|
|
76
73
|
const container = document.createElement("div");
|
|
77
74
|
render(
|
|
78
75
|
html`
|
|
79
|
-
<ef-configuration api-host="http://localhost:63315">
|
|
76
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
80
77
|
<div style="width: 400px; height: 300px;">
|
|
81
78
|
<ef-preview class="w-full h-[200px]">
|
|
82
79
|
<ef-timegroup mode="contain" class="w-full h-full bg-black">
|
|
@@ -96,9 +93,6 @@ const test = baseTest.extend<{
|
|
|
96
93
|
);
|
|
97
94
|
document.body.appendChild(container);
|
|
98
95
|
|
|
99
|
-
const config = container.querySelector("ef-configuration") as any;
|
|
100
|
-
config.signingURL = "";
|
|
101
|
-
|
|
102
96
|
const timegroup = container.querySelector("ef-timegroup") as EFTimegroup;
|
|
103
97
|
const video = container.querySelector("ef-video") as EFVideo;
|
|
104
98
|
const thumbnailStrip = container.querySelector(
|
|
@@ -174,6 +174,7 @@ export class EFThumbnailStrip extends LitElement {
|
|
|
174
174
|
|
|
175
175
|
// Target video element using the same pattern as EFSurface
|
|
176
176
|
// @ts-expect-error controller is intentionally not referenced directly to prevent GC
|
|
177
|
+
// biome-ignore lint/correctness/noUnusedPrivateClassMembers: Used for side effects
|
|
177
178
|
private _targetController: TargetController = new TargetController(
|
|
178
179
|
this as any,
|
|
179
180
|
);
|
|
@@ -417,10 +417,11 @@ describe("setting currentTime", () => {
|
|
|
417
417
|
);
|
|
418
418
|
localStorage.removeItem(timegroup.storageKey);
|
|
419
419
|
document.body.appendChild(timegroup);
|
|
420
|
+
await timegroup.updateComplete;
|
|
420
421
|
await timegroup.waitForMediaDurations();
|
|
421
422
|
|
|
422
|
-
|
|
423
|
-
await timegroup.
|
|
423
|
+
// Use the new seek() method which ensures everything is ready
|
|
424
|
+
await timegroup.seek(5_000_000); // 5000 seconds in ms, should clamp to 10s
|
|
424
425
|
|
|
425
426
|
const storedValue = localStorage.getItem(timegroup.storageKey);
|
|
426
427
|
assert.equal(storedValue, "10"); // Should store 10 (clamped from 5000 to duration)
|
|
@@ -521,11 +522,9 @@ describe("shouldWrapWithWorkbench", () => {
|
|
|
521
522
|
// TODO: need a way to define EF_INTERACTIVE in a test
|
|
522
523
|
});
|
|
523
524
|
|
|
524
|
-
test("should wrap if root-most timegroup", () => {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
root.appendChild(child);
|
|
528
|
-
assert.isTrue(child.shouldWrapWithWorkbench());
|
|
525
|
+
test.skip("should wrap if root-most timegroup", () => {
|
|
526
|
+
// TODO: This test requires EF_INTERACTIVE to be true, which is a module-level constant
|
|
527
|
+
// that cannot be modified in tests. Need a way to test this behavior.
|
|
529
528
|
});
|
|
530
529
|
|
|
531
530
|
test("should not wrap if contained within a preview context", () => {
|
|
@@ -616,23 +615,25 @@ describe("Dynamic content updates", () => {
|
|
|
616
615
|
const frameTaskB = timegroup.querySelector("test-frame-task-b")!;
|
|
617
616
|
const frameTaskC = timegroup.querySelector("test-frame-task-c")!;
|
|
618
617
|
|
|
619
|
-
//
|
|
618
|
+
// Following the initial update, frame tasks may run during initialization
|
|
620
619
|
await timegroup.updateComplete;
|
|
621
620
|
|
|
622
|
-
|
|
621
|
+
// frameTaskB should never run (not visible at time 0ms in sequence)
|
|
623
622
|
assert.equal(frameTaskB.frameTaskCount, 0);
|
|
624
|
-
assert.equal(frameTaskC.frameTaskCount, 1);
|
|
625
623
|
|
|
626
624
|
// Then we run them manually.
|
|
627
625
|
await timegroup.frameTask.run();
|
|
628
626
|
|
|
629
627
|
// At timeline time 0ms:
|
|
630
|
-
// - frameTaskA (0-1000ms) should run
|
|
631
|
-
// - frameTaskB (1000-2000ms) should NOT run
|
|
632
|
-
// - frameTaskC (0-1000ms) should run (inherits root positioning)
|
|
633
|
-
|
|
628
|
+
// - frameTaskA (0-1000ms) should have run (visible)
|
|
629
|
+
// - frameTaskB (1000-2000ms) should NOT run (not visible at time 0)
|
|
630
|
+
// - frameTaskC (0-1000ms) should have run (inherits root positioning, visible)
|
|
631
|
+
|
|
632
|
+
// Verify visible tasks have run at least once
|
|
633
|
+
assert.ok(frameTaskA.frameTaskCount > 0, "frameTaskA should have run");
|
|
634
|
+
assert.ok(frameTaskC.frameTaskCount > 0, "frameTaskC should have run");
|
|
635
|
+
// Verify non-visible task has never run
|
|
634
636
|
assert.equal(frameTaskB.frameTaskCount, 0); // Not visible at time 0
|
|
635
|
-
assert.equal(frameTaskC.frameTaskCount, 2); // Nested in B but inherits root positioning
|
|
636
637
|
});
|
|
637
638
|
});
|
|
638
639
|
|