@editframe/elements 0.18.27-beta.0 → 0.19.4-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/elements/EFMedia/AssetMediaEngine.d.ts +10 -0
- package/dist/elements/EFMedia/AssetMediaEngine.js +13 -1
- package/dist/elements/EFMedia/JitMediaEngine.d.ts +10 -0
- package/dist/elements/EFMedia/JitMediaEngine.js +12 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +16 -12
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +0 -4
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +0 -4
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +1 -1
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +3 -2
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +16 -12
- package/dist/elements/EFMedia.d.ts +2 -3
- package/dist/elements/EFMedia.js +0 -4
- package/dist/elements/EFTemporal.d.ts +9 -6
- package/dist/elements/EFTemporal.js +15 -12
- package/dist/elements/EFTimegroup.browsertest.d.ts +26 -0
- package/dist/elements/EFTimegroup.d.ts +13 -15
- package/dist/elements/EFTimegroup.js +123 -67
- package/dist/elements/EFVideo.d.ts +5 -1
- package/dist/elements/EFVideo.js +16 -8
- package/dist/elements/EFWaveform.js +2 -3
- package/dist/elements/FetchContext.browsertest.d.ts +0 -0
- package/dist/elements/FetchMixin.js +14 -9
- package/dist/elements/TimegroupController.js +2 -1
- package/dist/elements/updateAnimations.browsertest.d.ts +0 -0
- package/dist/elements/updateAnimations.d.ts +19 -9
- package/dist/elements/updateAnimations.js +64 -25
- package/dist/gui/ContextMixin.js +34 -27
- package/dist/gui/EFConfiguration.d.ts +1 -1
- package/dist/gui/EFConfiguration.js +1 -0
- package/dist/gui/EFFilmstrip.d.ts +1 -0
- package/dist/gui/EFFilmstrip.js +12 -14
- package/dist/gui/TWMixin.js +1 -1
- package/dist/style.css +1 -1
- package/dist/transcoding/cache/URLTokenDeduplicator.d.ts +38 -0
- package/dist/transcoding/cache/URLTokenDeduplicator.js +66 -0
- package/dist/transcoding/cache/URLTokenDeduplicator.test.d.ts +1 -0
- package/dist/transcoding/types/index.d.ts +10 -0
- package/package.json +2 -2
- package/src/elements/EFMedia/AssetMediaEngine.ts +16 -2
- package/src/elements/EFMedia/JitMediaEngine.ts +14 -0
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +0 -1
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +11 -4
- package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +0 -4
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +4 -1
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +0 -5
- package/src/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.ts +2 -2
- package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +7 -3
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +11 -4
- package/src/elements/EFMedia.browsertest.ts +13 -4
- package/src/elements/EFMedia.ts +6 -10
- package/src/elements/EFTemporal.ts +21 -26
- package/src/elements/EFTimegroup.browsertest.ts +186 -2
- package/src/elements/EFTimegroup.ts +205 -98
- package/src/elements/EFVideo.browsertest.ts +53 -132
- package/src/elements/EFVideo.ts +26 -13
- package/src/elements/EFWaveform.ts +2 -3
- package/src/elements/FetchContext.browsertest.ts +396 -0
- package/src/elements/FetchMixin.ts +25 -8
- package/src/elements/TimegroupController.ts +2 -1
- package/src/elements/updateAnimations.browsertest.ts +586 -0
- package/src/elements/updateAnimations.ts +113 -50
- package/src/gui/ContextMixin.browsertest.ts +4 -9
- package/src/gui/ContextMixin.ts +52 -33
- package/src/gui/EFConfiguration.ts +1 -1
- package/src/gui/EFFilmstrip.ts +15 -18
- package/src/transcoding/cache/URLTokenDeduplicator.test.ts +182 -0
- package/src/transcoding/cache/URLTokenDeduplicator.ts +101 -0
- package/src/transcoding/types/index.ts +11 -0
- package/test/EFVideo.framegen.browsertest.ts +1 -1
- package/test/setup.ts +2 -0
- package/types.json +1 -1
|
@@ -12,6 +12,7 @@ import { EFMedia } from "./EFMedia.js";
|
|
|
12
12
|
import "./EFTimegroup.js";
|
|
13
13
|
import type { EFTimegroup } from "./EFTimegroup.js";
|
|
14
14
|
import "./EFVideo.js";
|
|
15
|
+
import type { EFPreview } from "../gui/EFPreview.js";
|
|
15
16
|
import { UrlGenerator } from "../transcoding/utils/UrlGenerator.js";
|
|
16
17
|
import { AssetMediaEngine } from "./EFMedia/AssetMediaEngine.js";
|
|
17
18
|
import type { EFVideo } from "./EFVideo.js";
|
|
@@ -42,11 +43,16 @@ declare global {
|
|
|
42
43
|
|
|
43
44
|
const test = baseTest.extend<{
|
|
44
45
|
timegroup: EFTimegroup;
|
|
46
|
+
preview: EFPreview;
|
|
45
47
|
jitVideo: EFVideo;
|
|
46
48
|
configuration: EFConfiguration;
|
|
47
49
|
urlGenerator: UrlGenerator;
|
|
48
50
|
host: EFVideo;
|
|
49
51
|
}>({
|
|
52
|
+
preview: async ({}, use) => {
|
|
53
|
+
const preview = document.createElement("ef-preview");
|
|
54
|
+
await use(preview);
|
|
55
|
+
},
|
|
50
56
|
timegroup: async ({}, use) => {
|
|
51
57
|
const timegroup = document.createElement("ef-timegroup");
|
|
52
58
|
timegroup.setAttribute("mode", "contain");
|
|
@@ -59,6 +65,7 @@ const test = baseTest.extend<{
|
|
|
59
65
|
const apiHost = `${window.location.protocol}//${window.location.host}`;
|
|
60
66
|
configuration.setAttribute("api-host", apiHost);
|
|
61
67
|
configuration.apiHost = apiHost;
|
|
68
|
+
configuration.signingURL = "";
|
|
62
69
|
document.body.appendChild(configuration);
|
|
63
70
|
await use(configuration);
|
|
64
71
|
},
|
|
@@ -74,9 +81,10 @@ const test = baseTest.extend<{
|
|
|
74
81
|
host.src = "http://web:3000/head-moov-480p.mp4";
|
|
75
82
|
await use(host);
|
|
76
83
|
},
|
|
77
|
-
jitVideo: async ({ configuration, timegroup, host }, use) => {
|
|
84
|
+
jitVideo: async ({ configuration, timegroup, host, preview }, use) => {
|
|
78
85
|
timegroup.append(host);
|
|
79
|
-
configuration.append(
|
|
86
|
+
configuration.append(preview);
|
|
87
|
+
preview.append(timegroup);
|
|
80
88
|
await host.mediaEngineTask.run();
|
|
81
89
|
await use(host);
|
|
82
90
|
},
|
|
@@ -98,8 +106,7 @@ describe("JIT Media Engine", () => {
|
|
|
98
106
|
jitVideo,
|
|
99
107
|
expect,
|
|
100
108
|
}) => {
|
|
101
|
-
|
|
102
|
-
timegroup.currentTimeMs = 2200;
|
|
109
|
+
timegroup.currentTime = 2.2;
|
|
103
110
|
await timegroup.seekTask.taskComplete;
|
|
104
111
|
const sample = await jitVideo.unifiedVideoSeekTask.taskComplete;
|
|
105
112
|
expect(sample?.timestamp).toBeCloseTo(2.2, 1);
|
|
@@ -373,6 +380,7 @@ describe("EFMedia", () => {
|
|
|
373
380
|
const apiHost = `${window.location.protocol}//${window.location.host}`;
|
|
374
381
|
configuration.setAttribute("api-host", apiHost);
|
|
375
382
|
configuration.apiHost = apiHost;
|
|
383
|
+
configuration.signingURL = ""; // Disable URL signing for tests
|
|
376
384
|
document.body.appendChild(configuration);
|
|
377
385
|
await use(configuration);
|
|
378
386
|
// configuration.remove();
|
|
@@ -529,6 +537,7 @@ describe("EFMedia", () => {
|
|
|
529
537
|
const apiHost = `${window.location.protocol}//${window.location.host}`;
|
|
530
538
|
configuration.setAttribute("api-host", apiHost);
|
|
531
539
|
configuration.apiHost = apiHost;
|
|
540
|
+
configuration.signingURL = ""; // Disable URL signing for tests
|
|
532
541
|
document.body.appendChild(configuration);
|
|
533
542
|
await use(configuration);
|
|
534
543
|
},
|
package/src/elements/EFMedia.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { EFSourceMixin } from "./EFSourceMixin.js";
|
|
|
17
17
|
import { EFTemporal } from "./EFTemporal.js";
|
|
18
18
|
import { FetchMixin } from "./FetchMixin.js";
|
|
19
19
|
import { EFTargetable } from "./TargetController.ts";
|
|
20
|
-
import { updateAnimations } from "./updateAnimations.ts";
|
|
21
20
|
|
|
22
21
|
// EF_FRAMEGEN is a global instance created in EF_FRAMEGEN.ts
|
|
23
22
|
declare global {
|
|
@@ -78,9 +77,6 @@ export class EFMedia extends EFTargetable(
|
|
|
78
77
|
`,
|
|
79
78
|
];
|
|
80
79
|
|
|
81
|
-
@property({ type: Number })
|
|
82
|
-
currentTimeMs = 0;
|
|
83
|
-
|
|
84
80
|
/**
|
|
85
81
|
* Duration in milliseconds for audio buffering ahead of current time
|
|
86
82
|
* @domAttribute "audio-buffer-duration"
|
|
@@ -216,12 +212,12 @@ export class EFMedia extends EFTargetable(
|
|
|
216
212
|
if (changedProperties.has("ownCurrentTimeMs")) {
|
|
217
213
|
this.executeSeek(this.currentSourceTimeMs);
|
|
218
214
|
}
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
) {
|
|
223
|
-
|
|
224
|
-
}
|
|
215
|
+
// if (
|
|
216
|
+
// changedProperties.has("currentTime") ||
|
|
217
|
+
// changedProperties.has("ownCurrentTimeMs")
|
|
218
|
+
// ) {
|
|
219
|
+
// updateAnimations(this);
|
|
220
|
+
// }
|
|
225
221
|
}
|
|
226
222
|
|
|
227
223
|
get hasOwnDuration() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { consume, createContext } from "@lit/context";
|
|
2
2
|
import { Task } from "@lit/task";
|
|
3
|
-
import type { LitElement,
|
|
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
6
|
import { durationConverter } from "./durationConverter.js";
|
|
@@ -149,6 +149,13 @@ export declare class TemporalMixinInterface {
|
|
|
149
149
|
* played.
|
|
150
150
|
*/
|
|
151
151
|
get ownCurrentTimeMs(): number;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Element's current time for progress calculation.
|
|
155
|
+
* For timegroups: their timeline currentTimeMs
|
|
156
|
+
* For other temporal elements: their ownCurrentTimeMs
|
|
157
|
+
*/
|
|
158
|
+
get currentTimeMs(): number;
|
|
152
159
|
/**
|
|
153
160
|
* The current time of the element in milliseconds, adjusted for trimming.
|
|
154
161
|
*
|
|
@@ -211,11 +218,11 @@ const EF_TEMPORAL = Symbol("EF_TEMPORAL");
|
|
|
211
218
|
|
|
212
219
|
export const deepGetTemporalElements = (
|
|
213
220
|
element: Element,
|
|
214
|
-
temporals: TemporalMixinInterface
|
|
221
|
+
temporals: Array<TemporalMixinInterface & HTMLElement> = [],
|
|
215
222
|
) => {
|
|
216
223
|
for (const child of element.children) {
|
|
217
224
|
if (isEFTemporal(child)) {
|
|
218
|
-
temporals.push(child);
|
|
225
|
+
temporals.push(child as TemporalMixinInterface & HTMLElement);
|
|
219
226
|
}
|
|
220
227
|
deepGetTemporalElements(child, temporals);
|
|
221
228
|
}
|
|
@@ -224,11 +231,11 @@ export const deepGetTemporalElements = (
|
|
|
224
231
|
|
|
225
232
|
export const deepGetElementsWithFrameTasks = (
|
|
226
233
|
element: Element,
|
|
227
|
-
elements: Array<
|
|
234
|
+
elements: Array<TemporalMixinInterface & HTMLElement> = [],
|
|
228
235
|
) => {
|
|
229
236
|
for (const child of element.children) {
|
|
230
237
|
if ("frameTask" in child && child.frameTask instanceof Task) {
|
|
231
|
-
elements.push(child as
|
|
238
|
+
elements.push(child as TemporalMixinInterface & HTMLElement);
|
|
232
239
|
}
|
|
233
240
|
deepGetElementsWithFrameTasks(child, elements);
|
|
234
241
|
}
|
|
@@ -236,7 +243,7 @@ export const deepGetElementsWithFrameTasks = (
|
|
|
236
243
|
};
|
|
237
244
|
|
|
238
245
|
let temporalCache: Map<Element, TemporalMixinInterface[]>;
|
|
239
|
-
const resetTemporalCache = () => {
|
|
246
|
+
export const resetTemporalCache = () => {
|
|
240
247
|
temporalCache = new Map();
|
|
241
248
|
if (typeof requestAnimationFrame !== "undefined") {
|
|
242
249
|
requestAnimationFrame(resetTemporalCache);
|
|
@@ -597,6 +604,14 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
597
604
|
return 0;
|
|
598
605
|
}
|
|
599
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Element's current time for progress calculation.
|
|
609
|
+
* Non-timegroup temporal elements use their local time (ownCurrentTimeMs)
|
|
610
|
+
*/
|
|
611
|
+
get currentTimeMs() {
|
|
612
|
+
return this.ownCurrentTimeMs;
|
|
613
|
+
}
|
|
614
|
+
|
|
600
615
|
/**
|
|
601
616
|
* Used to calculate the internal currentTimeMs of the element. This is useful
|
|
602
617
|
* for mapping to internal media time codes for audio/video elements.
|
|
@@ -616,26 +631,6 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
616
631
|
}
|
|
617
632
|
},
|
|
618
633
|
});
|
|
619
|
-
|
|
620
|
-
protected updated(
|
|
621
|
-
changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
|
|
622
|
-
): void {
|
|
623
|
-
super.updated(changedProperties);
|
|
624
|
-
if (
|
|
625
|
-
changedProperties.has("currentTime") ||
|
|
626
|
-
changedProperties.has("ownCurrentTimeMs")
|
|
627
|
-
) {
|
|
628
|
-
const timelineTimeMs = (this.rootTimegroup ?? this).ownCurrentTimeMs;
|
|
629
|
-
if (
|
|
630
|
-
this.startTimeMs > timelineTimeMs ||
|
|
631
|
-
this.endTimeMs < timelineTimeMs
|
|
632
|
-
) {
|
|
633
|
-
this.style.display = "none";
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
this.style.display = "";
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
634
|
}
|
|
640
635
|
|
|
641
636
|
Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {
|
|
@@ -12,6 +12,12 @@ import { ContextMixin } from "../gui/ContextMixin.js";
|
|
|
12
12
|
import { EFTemporal } from "./EFTemporal.js";
|
|
13
13
|
// Need workbench to make workbench wrapping occurs
|
|
14
14
|
import "../gui/EFWorkbench.js";
|
|
15
|
+
// Additional imports for sequence boundary test
|
|
16
|
+
import "./EFVideo.js";
|
|
17
|
+
import "../gui/EFConfiguration.js";
|
|
18
|
+
import { Task } from "@lit/task";
|
|
19
|
+
import type { MediaEngine } from "../transcoding/types/index.js";
|
|
20
|
+
import { EFMedia } from "./EFMedia.js";
|
|
15
21
|
|
|
16
22
|
beforeEach(() => {
|
|
17
23
|
for (let i = 0; i < localStorage.length; i++) {
|
|
@@ -27,6 +33,61 @@ beforeEach(() => {
|
|
|
27
33
|
@customElement("test-context")
|
|
28
34
|
class TestContext extends ContextMixin(LitElement) {}
|
|
29
35
|
|
|
36
|
+
@customElement("timegroup-test-media")
|
|
37
|
+
class TimegroupTestMedia extends EFMedia {
|
|
38
|
+
mediaEngineTaskCount = 0;
|
|
39
|
+
mediaEngineTask = new Task(this, {
|
|
40
|
+
autoRun: false,
|
|
41
|
+
args: () => ["source", null] as const,
|
|
42
|
+
task: () => {
|
|
43
|
+
this.mediaEngineTaskCount++;
|
|
44
|
+
return Promise.resolve({} as unknown as MediaEngine);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@customElement("test-frame-task-a")
|
|
50
|
+
class TestFrameTaskA extends EFTemporal(LitElement) {
|
|
51
|
+
frameTaskCount = 0;
|
|
52
|
+
|
|
53
|
+
frameTask = new Task(this, {
|
|
54
|
+
autoRun: false,
|
|
55
|
+
args: () => [],
|
|
56
|
+
task: () => {
|
|
57
|
+
this.frameTaskCount++;
|
|
58
|
+
return Promise.resolve();
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@customElement("test-frame-task-b")
|
|
64
|
+
class TestFrameTaskB extends EFTemporal(LitElement) {
|
|
65
|
+
frameTaskCount = 0;
|
|
66
|
+
|
|
67
|
+
frameTask = new Task(this, {
|
|
68
|
+
autoRun: false,
|
|
69
|
+
args: () => [],
|
|
70
|
+
task: () => {
|
|
71
|
+
this.frameTaskCount++;
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@customElement("test-frame-task-c")
|
|
78
|
+
class TestFrameTaskC extends EFTemporal(LitElement) {
|
|
79
|
+
frameTaskCount = 0;
|
|
80
|
+
|
|
81
|
+
frameTask = new Task(this, {
|
|
82
|
+
autoRun: false,
|
|
83
|
+
args: () => [],
|
|
84
|
+
task: () => {
|
|
85
|
+
this.frameTaskCount++;
|
|
86
|
+
return Promise.resolve();
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
30
91
|
@customElement("test-temporal")
|
|
31
92
|
class TestTemporal extends EFTemporal(LitElement) {
|
|
32
93
|
get hasOwnDuration(): boolean {
|
|
@@ -38,20 +99,24 @@ declare global {
|
|
|
38
99
|
interface HTMLElementTagNameMap {
|
|
39
100
|
"test-temporal": TestTemporal;
|
|
40
101
|
"test-context": TestContext;
|
|
102
|
+
"timegroup-test-media": TimegroupTestMedia;
|
|
103
|
+
"test-frame-task-a": TestFrameTaskA;
|
|
104
|
+
"test-frame-task-b": TestFrameTaskB;
|
|
105
|
+
"test-frame-task-c": TestFrameTaskC;
|
|
41
106
|
}
|
|
42
107
|
}
|
|
43
108
|
|
|
44
109
|
const renderTimegroup = (result: TemplateResult) => {
|
|
45
110
|
const container = document.createElement("div");
|
|
46
111
|
litRender(result, container);
|
|
47
|
-
const firstChild = container.
|
|
112
|
+
const firstChild = container.querySelector("ef-timegroup");
|
|
48
113
|
if (!firstChild) {
|
|
49
114
|
throw new Error("No first child found");
|
|
50
115
|
}
|
|
51
116
|
if (!(firstChild instanceof EFTimegroup)) {
|
|
52
117
|
throw new Error("First child is not an EFTimegroup");
|
|
53
118
|
}
|
|
54
|
-
document.body.appendChild(
|
|
119
|
+
document.body.appendChild(container);
|
|
55
120
|
return firstChild;
|
|
56
121
|
};
|
|
57
122
|
|
|
@@ -436,3 +501,122 @@ describe("DOM nodes", () => {
|
|
|
436
501
|
assert.equal(timegroup.durationMs, 10_000);
|
|
437
502
|
});
|
|
438
503
|
});
|
|
504
|
+
|
|
505
|
+
describe("Dynamic content updates", () => {
|
|
506
|
+
test("updates duration when new child temporal elements are added dynamically", async () => {
|
|
507
|
+
// Create a sequence timegroup with initial children
|
|
508
|
+
const timegroup = renderTimegroup(
|
|
509
|
+
html`<ef-timegroup mode="sequence">
|
|
510
|
+
<ef-timegroup mode="fixed" duration="3s"></ef-timegroup>
|
|
511
|
+
<ef-timegroup mode="fixed" duration="2s"></ef-timegroup>
|
|
512
|
+
</ef-timegroup>`,
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
// Initial duration should be 5 seconds (3s + 2s)
|
|
516
|
+
assert.equal(timegroup.durationMs, 5_000);
|
|
517
|
+
assert.equal(timegroup.childTemporals.length, 2);
|
|
518
|
+
|
|
519
|
+
// Dynamically add a new child element
|
|
520
|
+
const newChild = document.createElement("ef-timegroup");
|
|
521
|
+
newChild.setAttribute("mode", "fixed");
|
|
522
|
+
newChild.setAttribute("duration", "4s");
|
|
523
|
+
timegroup.appendChild(newChild);
|
|
524
|
+
|
|
525
|
+
// Wait for slot change event to process
|
|
526
|
+
await timegroup.updateComplete;
|
|
527
|
+
|
|
528
|
+
// Duration should now include the new child (3s + 2s + 4s = 9s)
|
|
529
|
+
assert.equal(timegroup.durationMs, 9_000);
|
|
530
|
+
assert.equal(timegroup.childTemporals.length, 3);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
test("updates duration when child temporal elements are removed dynamically", async () => {
|
|
534
|
+
// Create a contain timegroup with initial children
|
|
535
|
+
const timegroup = renderTimegroup(
|
|
536
|
+
html`<ef-timegroup mode="contain">
|
|
537
|
+
<ef-timegroup id="child1" mode="fixed" duration="5s"></ef-timegroup>
|
|
538
|
+
<ef-timegroup id="child2" mode="fixed" duration="8s"></ef-timegroup>
|
|
539
|
+
<ef-timegroup id="child3" mode="fixed" duration="3s"></ef-timegroup>
|
|
540
|
+
</ef-timegroup>`,
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
// Initial duration should be max of children (8s)
|
|
544
|
+
assert.equal(timegroup.durationMs, 8_000);
|
|
545
|
+
assert.equal(timegroup.childTemporals.length, 3);
|
|
546
|
+
|
|
547
|
+
// Remove the longest duration child
|
|
548
|
+
const child2 = timegroup.querySelector("#child2");
|
|
549
|
+
child2?.remove();
|
|
550
|
+
|
|
551
|
+
// Wait for slot change event to process
|
|
552
|
+
await timegroup.updateComplete;
|
|
553
|
+
|
|
554
|
+
// Duration should now be max of remaining children (5s)
|
|
555
|
+
assert.equal(timegroup.durationMs, 5_000);
|
|
556
|
+
assert.equal(timegroup.childTemporals.length, 2);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
describe("frameTask", () => {
|
|
560
|
+
test("executes all nested frame tasks", async () => {
|
|
561
|
+
const timegroup = renderTimegroup(
|
|
562
|
+
html`<ef-timegroup mode="sequence">
|
|
563
|
+
<test-frame-task-a duration="1s"></test-frame-task-a>
|
|
564
|
+
<div>
|
|
565
|
+
<test-frame-task-b duration="1s">
|
|
566
|
+
<test-frame-task-c duration="1s"></test-frame-task-c>
|
|
567
|
+
</test-frame-task-b>
|
|
568
|
+
</div>
|
|
569
|
+
</ef-timegroup>`,
|
|
570
|
+
);
|
|
571
|
+
const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
|
|
572
|
+
const frameTaskB = timegroup.querySelector("test-frame-task-b")!;
|
|
573
|
+
const frameTaskC = timegroup.querySelector("test-frame-task-c")!;
|
|
574
|
+
|
|
575
|
+
assert.equal(frameTaskA.frameTaskCount, 0);
|
|
576
|
+
assert.equal(frameTaskB.frameTaskCount, 0);
|
|
577
|
+
assert.equal(frameTaskC.frameTaskCount, 0);
|
|
578
|
+
|
|
579
|
+
await timegroup.frameTask.run();
|
|
580
|
+
|
|
581
|
+
// At timeline time 0ms:
|
|
582
|
+
// - frameTaskA (0-1000ms) should run
|
|
583
|
+
// - frameTaskB (1000-2000ms) should NOT run
|
|
584
|
+
// - frameTaskC (0-1000ms) should run (inherits root positioning)
|
|
585
|
+
assert.equal(frameTaskA.frameTaskCount, 1);
|
|
586
|
+
assert.equal(frameTaskB.frameTaskCount, 0); // Not visible at time 0
|
|
587
|
+
assert.equal(frameTaskC.frameTaskCount, 1); // Nested in B but inherits root positioning
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
describe("seekTask", () => {
|
|
592
|
+
test("does not execute if not the root timegroup", async () => {
|
|
593
|
+
const timegroup = renderTimegroup(
|
|
594
|
+
html`<ef-timegroup mode="sequence">
|
|
595
|
+
<ef-timegroup mode="fixed" duration="3s">
|
|
596
|
+
<test-frame-task-a></test-frame-task-a>
|
|
597
|
+
</ef-timegroup>
|
|
598
|
+
</ef-timegroup>`,
|
|
599
|
+
);
|
|
600
|
+
const nonRootTimegroup = timegroup.querySelector("ef-timegroup")!;
|
|
601
|
+
const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
|
|
602
|
+
assert.equal(frameTaskA.frameTaskCount, 0);
|
|
603
|
+
await nonRootTimegroup.seekTask.run();
|
|
604
|
+
assert.equal(frameTaskA.frameTaskCount, 0);
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
test("waits for media durations", async () => {
|
|
608
|
+
const timegroup = renderTimegroup(
|
|
609
|
+
html`
|
|
610
|
+
<ef-preview>
|
|
611
|
+
<ef-timegroup mode="sequence">
|
|
612
|
+
<timegroup-test-media></timegroup-test-media>
|
|
613
|
+
</ef-timegroup>
|
|
614
|
+
</ef-preview>`,
|
|
615
|
+
);
|
|
616
|
+
const media = timegroup.querySelector("timegroup-test-media")!;
|
|
617
|
+
assert.equal(media.mediaEngineTaskCount, 0);
|
|
618
|
+
await timegroup.seekTask.run();
|
|
619
|
+
assert.equal(media.mediaEngineTaskCount, 1);
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
});
|