@editframe/elements 0.19.2-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/EFTimegroup.d.ts +1 -6
- package/dist/elements/EFTimegroup.js +13 -6
- package/dist/elements/updateAnimations.js +1 -1
- package/package.json +2 -2
- package/src/elements/EFTimegroup.ts +18 -7
- package/src/elements/updateAnimations.browsertest.ts +29 -2
- package/src/elements/updateAnimations.ts +1 -1
- package/types.json +1 -1
|
@@ -33,12 +33,7 @@ export declare class EFTimegroup extends EFTimegroup_base {
|
|
|
33
33
|
getPendingFrameTasks(signal?: AbortSignal): Promise<Task<readonly unknown[], unknown>[]>;
|
|
34
34
|
waitForNestedUpdates(signal?: AbortSignal): Promise<void>;
|
|
35
35
|
waitForFrameTasks(): Promise<void>;
|
|
36
|
-
|
|
37
|
-
* Wait for all media elements to load their initial segments.
|
|
38
|
-
* Ideally we would only need the extracted index json data, but
|
|
39
|
-
* that caused issues with constructing audio data. We had negative durations
|
|
40
|
-
* in calculations and it was not clear why.
|
|
41
|
-
*/
|
|
36
|
+
mediaDurationsPromise: Promise<void> | undefined;
|
|
42
37
|
waitForMediaDurations(): Promise<void>;
|
|
43
38
|
get childTemporals(): import('./EFTemporal.js').TemporalMixinInterface[];
|
|
44
39
|
get contextProvider(): import('../gui/ContextMixin.js').ContextMixinInterface | null;
|
|
@@ -32,6 +32,7 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
|
|
|
32
32
|
this._mode = "contain";
|
|
33
33
|
this._overlapMs = 0;
|
|
34
34
|
this.fit = "none";
|
|
35
|
+
this.mediaDurationsPromise = void 0;
|
|
35
36
|
this.frameTask = new Task(this, {
|
|
36
37
|
autoRun: false,
|
|
37
38
|
args: () => [this.ownCurrentTimeMs, this.currentTimeMs],
|
|
@@ -90,17 +91,16 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
|
|
|
90
91
|
#pendingSeekTime;
|
|
91
92
|
#processingPendingSeek = false;
|
|
92
93
|
set currentTime(time) {
|
|
94
|
+
time = Math.max(0, time);
|
|
93
95
|
if (!this.isRootTimegroup) return;
|
|
94
96
|
if (Number.isNaN(time)) return;
|
|
95
97
|
if (time === this.#currentTime && !this.#processingPendingSeek) return;
|
|
96
98
|
if (this.#pendingSeekTime === time) return;
|
|
97
99
|
if (this.#seekInProgress) {
|
|
98
|
-
console.trace("pending seek to", time);
|
|
99
100
|
this.#pendingSeekTime = time;
|
|
100
101
|
this.#currentTime = time;
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
103
|
-
console.trace("seeking to", time);
|
|
104
104
|
this.#currentTime = time;
|
|
105
105
|
this.#seekInProgress = true;
|
|
106
106
|
this.seekTask.run().finally(() => {
|
|
@@ -161,9 +161,12 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
|
|
|
161
161
|
}
|
|
162
162
|
connectedCallback() {
|
|
163
163
|
super.connectedCallback();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
this.waitForMediaDurations().then(() => {
|
|
165
|
+
if (this.id) {
|
|
166
|
+
const maybeLoadedTime = this.maybeLoadTimeFromLocalStorage();
|
|
167
|
+
if (maybeLoadedTime !== void 0) this.currentTime = maybeLoadedTime;
|
|
168
|
+
}
|
|
169
|
+
if (EF_INTERACTIVE && this.seekTask.status === TaskStatus.INITIAL) this.seekTask.run();
|
|
167
170
|
});
|
|
168
171
|
if (this.parentTimegroup) new TimegroupController(this.parentTimegroup, this);
|
|
169
172
|
if (this.shouldWrapWithWorkbench()) this.wrapWithWorkbench();
|
|
@@ -256,13 +259,17 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
|
|
|
256
259
|
return element.frameTask.run();
|
|
257
260
|
}));
|
|
258
261
|
}
|
|
262
|
+
async waitForMediaDurations() {
|
|
263
|
+
if (!this.mediaDurationsPromise) this.mediaDurationsPromise = this.#waitForMediaDurations();
|
|
264
|
+
return this.mediaDurationsPromise;
|
|
265
|
+
}
|
|
259
266
|
/**
|
|
260
267
|
* Wait for all media elements to load their initial segments.
|
|
261
268
|
* Ideally we would only need the extracted index json data, but
|
|
262
269
|
* that caused issues with constructing audio data. We had negative durations
|
|
263
270
|
* in calculations and it was not clear why.
|
|
264
271
|
*/
|
|
265
|
-
async waitForMediaDurations() {
|
|
272
|
+
async #waitForMediaDurations() {
|
|
266
273
|
await this.updateComplete;
|
|
267
274
|
const mediaElements = deepGetMediaElements(this);
|
|
268
275
|
await Promise.all(mediaElements.map((m) => m.mediaEngineTask.value ? Promise.resolve() : m.mediaEngineTask.run()));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { deepGetTemporalElements, isEFTemporal } from "./EFTemporal.js";
|
|
2
|
-
const ANIMATION_PRECISION_OFFSET =
|
|
2
|
+
const ANIMATION_PRECISION_OFFSET = .001;
|
|
3
3
|
const DEFAULT_ANIMATION_ITERATIONS = 1;
|
|
4
4
|
const PROGRESS_PROPERTY = "--ef-progress";
|
|
5
5
|
const DURATION_PROPERTY = "--ef-duration";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/elements",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.4-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"license": "UNLICENSED",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@bramus/style-observer": "^1.3.0",
|
|
30
|
-
"@editframe/assets": "0.19.
|
|
30
|
+
"@editframe/assets": "0.19.4-beta.0",
|
|
31
31
|
"@lit/context": "^1.1.2",
|
|
32
32
|
"@lit/task": "^1.0.1",
|
|
33
33
|
"d3": "^7.9.0",
|
|
@@ -106,6 +106,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
106
106
|
|
|
107
107
|
@property({ type: Number, attribute: "currenttime" })
|
|
108
108
|
set currentTime(time: number) {
|
|
109
|
+
time = Math.max(0, time);
|
|
109
110
|
if (!this.isRootTimegroup) {
|
|
110
111
|
return;
|
|
111
112
|
}
|
|
@@ -120,12 +121,10 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
if (this.#seekInProgress) {
|
|
123
|
-
console.trace("pending seek to", time);
|
|
124
124
|
this.#pendingSeekTime = time;
|
|
125
125
|
this.#currentTime = time;
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
-
console.trace("seeking to", time);
|
|
129
128
|
|
|
130
129
|
this.#currentTime = time;
|
|
131
130
|
// This will be set to false in the seekTask
|
|
@@ -212,14 +211,17 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
212
211
|
|
|
213
212
|
connectedCallback() {
|
|
214
213
|
super.connectedCallback();
|
|
215
|
-
|
|
216
|
-
this.
|
|
214
|
+
this.waitForMediaDurations().then(() => {
|
|
215
|
+
if (this.id) {
|
|
217
216
|
const maybeLoadedTime = this.maybeLoadTimeFromLocalStorage();
|
|
218
217
|
if (maybeLoadedTime !== undefined) {
|
|
219
218
|
this.currentTime = maybeLoadedTime;
|
|
220
219
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
220
|
+
}
|
|
221
|
+
if (EF_INTERACTIVE && this.seekTask.status === TaskStatus.INITIAL) {
|
|
222
|
+
this.seekTask.run();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
223
225
|
|
|
224
226
|
if (this.parentTimegroup) {
|
|
225
227
|
new TimegroupController(this.parentTimegroup, this);
|
|
@@ -376,13 +378,22 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
376
378
|
);
|
|
377
379
|
}
|
|
378
380
|
|
|
381
|
+
mediaDurationsPromise: Promise<void> | undefined = undefined;
|
|
382
|
+
|
|
383
|
+
async waitForMediaDurations() {
|
|
384
|
+
if (!this.mediaDurationsPromise) {
|
|
385
|
+
this.mediaDurationsPromise = this.#waitForMediaDurations();
|
|
386
|
+
}
|
|
387
|
+
return this.mediaDurationsPromise;
|
|
388
|
+
}
|
|
389
|
+
|
|
379
390
|
/**
|
|
380
391
|
* Wait for all media elements to load their initial segments.
|
|
381
392
|
* Ideally we would only need the extracted index json data, but
|
|
382
393
|
* that caused issues with constructing audio data. We had negative durations
|
|
383
394
|
* in calculations and it was not clear why.
|
|
384
395
|
*/
|
|
385
|
-
async waitForMediaDurations() {
|
|
396
|
+
async #waitForMediaDurations() {
|
|
386
397
|
// We must await updateComplete to ensure all media elements inside this are connected
|
|
387
398
|
// and will match deepGetMediaElements
|
|
388
399
|
await this.updateComplete;
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import "./EFTimegroup.js";
|
|
9
9
|
|
|
10
|
-
// Import the constant for tests that need to check animation precision
|
|
11
|
-
|
|
12
10
|
beforeEach(() => {
|
|
13
11
|
// Clean up DOM
|
|
14
12
|
while (document.body.children.length) {
|
|
@@ -415,6 +413,35 @@ describe("Timeline Element Synchronizer", () => {
|
|
|
415
413
|
|
|
416
414
|
assert.equal(animation.playState, "paused");
|
|
417
415
|
});
|
|
416
|
+
|
|
417
|
+
test("keeps completed animations available for scrubbing", async () => {
|
|
418
|
+
// Create a timegroup with 10s duration
|
|
419
|
+
const timegroup = document.createElement("ef-timegroup") as EFTimegroup;
|
|
420
|
+
timegroup.setAttribute("mode", "fixed");
|
|
421
|
+
timegroup.setAttribute("duration", "10000ms");
|
|
422
|
+
document.body.appendChild(timegroup);
|
|
423
|
+
|
|
424
|
+
// Create a child element with a 5s animation
|
|
425
|
+
const child = document.createElement("div");
|
|
426
|
+
timegroup.appendChild(child);
|
|
427
|
+
|
|
428
|
+
child.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
429
|
+
duration: 5000, // 5s animation
|
|
430
|
+
iterations: 1,
|
|
431
|
+
delay: 0,
|
|
432
|
+
});
|
|
433
|
+
timegroup.currentTime = 6;
|
|
434
|
+
await timegroup.seekTask.run();
|
|
435
|
+
|
|
436
|
+
// Animation should still be available even though timeline (6s) > animation duration (5s)
|
|
437
|
+
// This prevents animations from being removed, enabling scrubbing backwards
|
|
438
|
+
const animations = timegroup.getAnimations({ subtree: true });
|
|
439
|
+
assert.equal(
|
|
440
|
+
animations.length,
|
|
441
|
+
1,
|
|
442
|
+
"REGRESSION TEST: Animation should remain available for scrubbing. This would fail with Number.EPSILON due to insufficient precision offset.",
|
|
443
|
+
);
|
|
444
|
+
});
|
|
418
445
|
});
|
|
419
446
|
|
|
420
447
|
describe("edge cases", () => {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
export type AnimatableElement = TemporalMixinInterface & HTMLElement;
|
|
9
9
|
|
|
10
10
|
// Constants
|
|
11
|
-
const ANIMATION_PRECISION_OFFSET =
|
|
11
|
+
const ANIMATION_PRECISION_OFFSET = 0.001;
|
|
12
12
|
const DEFAULT_ANIMATION_ITERATIONS = 1;
|
|
13
13
|
const PROGRESS_PROPERTY = "--ef-progress";
|
|
14
14
|
const DURATION_PROPERTY = "--ef-duration";
|