@editframe/elements 0.31.0-beta.0 → 0.31.0-beta.1
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/EFAudio.d.ts +2 -2
- package/dist/elements/EFCaptions.d.ts +12 -12
- package/dist/elements/EFImage.d.ts +4 -4
- package/dist/elements/EFMedia.d.ts +2 -2
- package/dist/elements/EFText.d.ts +4 -4
- package/dist/elements/EFThumbnailStrip.d.ts +11 -0
- package/dist/elements/EFThumbnailStrip.js +95 -13
- package/dist/elements/EFThumbnailStrip.js.map +1 -1
- package/dist/elements/EFTimegroup.d.ts +12 -0
- package/dist/elements/EFTimegroup.js +18 -0
- package/dist/elements/EFTimegroup.js.map +1 -1
- package/dist/elements/EFVideo.d.ts +4 -4
- package/dist/elements/SessionThumbnailCache.js +7 -5
- package/dist/elements/SessionThumbnailCache.js.map +1 -1
- package/dist/gui/EFConfiguration.d.ts +4 -4
- package/dist/gui/EFWorkbench.d.ts +4 -4
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/TWMixin.js.map +1 -1
- package/dist/preview/renderTimegroupToCanvas.js +2 -9
- package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
- package/dist/preview/workers/WorkerPool.js.map +1 -1
- package/dist/preview/workers/encoderWorkerInline.js +103 -0
- package/dist/preview/workers/encoderWorkerInline.js.map +1 -0
- package/dist/style.css +3 -0
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { MediaEngine } from "../transcoding/types/index.js";
|
|
|
2
2
|
import { EFMedia } from "./EFMedia.js";
|
|
3
3
|
import * as _lit_task8 from "@lit/task";
|
|
4
4
|
import { Task } from "@lit/task";
|
|
5
|
-
import * as
|
|
5
|
+
import * as lit_html2 from "lit-html";
|
|
6
6
|
import * as lit_html_directives_ref_js1 from "lit-html/directives/ref.js";
|
|
7
7
|
|
|
8
8
|
//#region src/elements/EFAudio.d.ts
|
|
@@ -20,7 +20,7 @@ declare class EFAudio extends EFAudio_base {
|
|
|
20
20
|
volume: number;
|
|
21
21
|
audioElementRef: lit_html_directives_ref_js1.Ref<HTMLAudioElement>;
|
|
22
22
|
protected updated(changedProperties: Map<PropertyKey, unknown>): void;
|
|
23
|
-
render():
|
|
23
|
+
render(): lit_html2.TemplateResult<1>;
|
|
24
24
|
frameTask: Task<readonly [_lit_task8.TaskStatus, _lit_task8.TaskStatus, _lit_task8.TaskStatus, _lit_task8.TaskStatus], void>;
|
|
25
25
|
/**
|
|
26
26
|
* Legacy getter for fragment index task (maps to audioSegmentIdTask)
|
|
@@ -4,9 +4,9 @@ import { FetchMixinInterface } from "./FetchMixin.js";
|
|
|
4
4
|
import { EFVideo } from "./EFVideo.js";
|
|
5
5
|
import { EFAudio } from "./EFAudio.js";
|
|
6
6
|
import { Task, TaskStatus } from "@lit/task";
|
|
7
|
-
import * as
|
|
7
|
+
import * as lit4 from "lit";
|
|
8
8
|
import { LitElement, PropertyValueMap } from "lit";
|
|
9
|
-
import * as
|
|
9
|
+
import * as lit_html4 from "lit-html";
|
|
10
10
|
|
|
11
11
|
//#region src/elements/EFCaptions.d.ts
|
|
12
12
|
interface WordSegment {
|
|
@@ -25,8 +25,8 @@ interface Caption {
|
|
|
25
25
|
}
|
|
26
26
|
declare const EFCaptionsActiveWord_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
|
|
27
27
|
declare class EFCaptionsActiveWord extends EFCaptionsActiveWord_base {
|
|
28
|
-
static styles:
|
|
29
|
-
render():
|
|
28
|
+
static styles: lit4.CSSResult[];
|
|
29
|
+
render(): lit_html4.TemplateResult<1> | undefined;
|
|
30
30
|
wordStartMs: number;
|
|
31
31
|
wordEndMs: number;
|
|
32
32
|
wordText: string;
|
|
@@ -38,8 +38,8 @@ declare class EFCaptionsActiveWord extends EFCaptionsActiveWord_base {
|
|
|
38
38
|
}
|
|
39
39
|
declare const EFCaptionsSegment_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
|
|
40
40
|
declare class EFCaptionsSegment extends EFCaptionsSegment_base {
|
|
41
|
-
static styles:
|
|
42
|
-
render():
|
|
41
|
+
static styles: lit4.CSSResult[];
|
|
42
|
+
render(): lit_html4.TemplateResult<1> | undefined;
|
|
43
43
|
segmentStartMs: number;
|
|
44
44
|
segmentEndMs: number;
|
|
45
45
|
segmentText: string;
|
|
@@ -49,8 +49,8 @@ declare class EFCaptionsSegment extends EFCaptionsSegment_base {
|
|
|
49
49
|
get durationMs(): number;
|
|
50
50
|
}
|
|
51
51
|
declare class EFCaptionsBeforeActiveWord extends EFCaptionsSegment {
|
|
52
|
-
static styles:
|
|
53
|
-
render():
|
|
52
|
+
static styles: lit4.CSSResult[];
|
|
53
|
+
render(): lit_html4.TemplateResult<1> | undefined;
|
|
54
54
|
hidden: boolean;
|
|
55
55
|
segmentText: string;
|
|
56
56
|
segmentStartMs: number;
|
|
@@ -60,8 +60,8 @@ declare class EFCaptionsBeforeActiveWord extends EFCaptionsSegment {
|
|
|
60
60
|
get durationMs(): number;
|
|
61
61
|
}
|
|
62
62
|
declare class EFCaptionsAfterActiveWord extends EFCaptionsSegment {
|
|
63
|
-
static styles:
|
|
64
|
-
render():
|
|
63
|
+
static styles: lit4.CSSResult[];
|
|
64
|
+
render(): lit_html4.TemplateResult<1> | undefined;
|
|
65
65
|
hidden: boolean;
|
|
66
66
|
segmentText: string;
|
|
67
67
|
segmentStartMs: number;
|
|
@@ -73,7 +73,7 @@ declare class EFCaptionsAfterActiveWord extends EFCaptionsSegment {
|
|
|
73
73
|
declare const EFCaptions_base: (new (...args: any[]) => EFSourceMixinInterface) & (new (...args: any[]) => TemporalMixinInterface) & (new (...args: any[]) => FetchMixinInterface) & typeof LitElement;
|
|
74
74
|
declare class EFCaptions extends EFCaptions_base {
|
|
75
75
|
#private;
|
|
76
|
-
static styles:
|
|
76
|
+
static styles: lit4.CSSResult[];
|
|
77
77
|
targetSelector: string;
|
|
78
78
|
set target(value: string);
|
|
79
79
|
wordStyle: string;
|
|
@@ -96,7 +96,7 @@ declare class EFCaptions extends EFCaptions_base {
|
|
|
96
96
|
segmentContainers: HTMLCollectionOf<EFCaptionsSegment>;
|
|
97
97
|
beforeActiveWordContainers: HTMLCollectionOf<EFCaptionsBeforeActiveWord>;
|
|
98
98
|
afterActiveWordContainers: HTMLCollectionOf<EFCaptionsAfterActiveWord>;
|
|
99
|
-
render():
|
|
99
|
+
render(): lit_html4.TemplateResult<1>;
|
|
100
100
|
transcriptionsPath(): string | null;
|
|
101
101
|
captionsPath(): string | null;
|
|
102
102
|
protected md5SumLoader: Task<readonly [string, typeof fetch], any>;
|
|
@@ -3,21 +3,21 @@ import { TemporalMixinInterface } from "./EFTemporal.js";
|
|
|
3
3
|
import { FetchMixinInterface } from "./FetchMixin.js";
|
|
4
4
|
import * as _lit_task0 from "@lit/task";
|
|
5
5
|
import { Task } from "@lit/task";
|
|
6
|
-
import * as
|
|
6
|
+
import * as lit1 from "lit";
|
|
7
7
|
import { LitElement } from "lit";
|
|
8
|
-
import * as
|
|
8
|
+
import * as lit_html1 from "lit-html";
|
|
9
9
|
import * as lit_html_directives_ref_js0 from "lit-html/directives/ref.js";
|
|
10
10
|
|
|
11
11
|
//#region src/elements/EFImage.d.ts
|
|
12
12
|
declare const EFImage_base: (new (...args: any[]) => TemporalMixinInterface) & (new (...args: any[]) => EFSourceMixinInterface) & (new (...args: any[]) => FetchMixinInterface) & typeof LitElement;
|
|
13
13
|
declare class EFImage extends EFImage_base {
|
|
14
14
|
#private;
|
|
15
|
-
static styles:
|
|
15
|
+
static styles: lit1.CSSResult[];
|
|
16
16
|
imageRef: lit_html_directives_ref_js0.Ref<HTMLImageElement>;
|
|
17
17
|
canvasRef: lit_html_directives_ref_js0.Ref<HTMLCanvasElement>;
|
|
18
18
|
set assetId(value: string | null);
|
|
19
19
|
get assetId(): string | null;
|
|
20
|
-
render():
|
|
20
|
+
render(): lit_html1.TemplateResult<1>;
|
|
21
21
|
private isDirectUrl;
|
|
22
22
|
assetPath(): string;
|
|
23
23
|
get hasOwnDuration(): boolean;
|
|
@@ -9,7 +9,7 @@ import { AudioBufferState } from "./EFMedia/audioTasks/makeAudioBufferTask.js";
|
|
|
9
9
|
import { ControllableInterface } from "../gui/Controllable.js";
|
|
10
10
|
import { UrlGenerator } from "../transcoding/utils/UrlGenerator.js";
|
|
11
11
|
import * as _lit_task0 from "@lit/task";
|
|
12
|
-
import * as
|
|
12
|
+
import * as lit2 from "lit";
|
|
13
13
|
import { LitElement, PropertyValueMap } from "lit";
|
|
14
14
|
import * as mediabunny0 from "mediabunny";
|
|
15
15
|
|
|
@@ -34,7 +34,7 @@ declare class EFMedia extends EFMedia_base {
|
|
|
34
34
|
*/
|
|
35
35
|
get requiredTracks(): "audio" | "video" | "both";
|
|
36
36
|
static get observedAttributes(): string[];
|
|
37
|
-
static styles:
|
|
37
|
+
static styles: lit2.CSSResult[];
|
|
38
38
|
/**
|
|
39
39
|
* Duration in milliseconds for audio buffering ahead of current time
|
|
40
40
|
* @domAttribute "audio-buffer-duration"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { TemporalMixinInterface } from "./EFTemporal.js";
|
|
2
2
|
import { EFTextSegment } from "./EFTextSegment.js";
|
|
3
|
-
import * as
|
|
3
|
+
import * as lit0 from "lit";
|
|
4
4
|
import { LitElement, PropertyValueMap } from "lit";
|
|
5
|
-
import * as
|
|
5
|
+
import * as lit_html0 from "lit-html";
|
|
6
6
|
|
|
7
7
|
//#region src/elements/EFText.d.ts
|
|
8
8
|
type SplitMode = "line" | "word" | "char";
|
|
9
9
|
declare const EFText_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
|
|
10
10
|
declare class EFText extends EFText_base {
|
|
11
|
-
static styles:
|
|
11
|
+
static styles: lit0.CSSResult[];
|
|
12
12
|
split: SplitMode;
|
|
13
13
|
private validateSplit;
|
|
14
14
|
staggerMs?: number;
|
|
@@ -19,7 +19,7 @@ declare class EFText extends EFText_base {
|
|
|
19
19
|
private _textContent;
|
|
20
20
|
private _templateElement;
|
|
21
21
|
private _segmentsReadyResolvers;
|
|
22
|
-
render():
|
|
22
|
+
render(): lit_html0.TemplateResult<1>;
|
|
23
23
|
set textContent(value: string | null);
|
|
24
24
|
get textContent(): string;
|
|
25
25
|
/**
|
|
@@ -48,6 +48,10 @@ declare class EFThumbnailStrip extends LitElement {
|
|
|
48
48
|
private _renderRequested;
|
|
49
49
|
/** Track if any thumbnails have been loaded (for ready event) */
|
|
50
50
|
private _hasLoadedThumbnails;
|
|
51
|
+
/** Track the last epoch we loaded thumbnails for */
|
|
52
|
+
private _lastLoadedEpoch;
|
|
53
|
+
/** Track layout parameters to avoid unnecessary slot recreation */
|
|
54
|
+
private _lastLayoutParams;
|
|
51
55
|
connectedCallback(): void;
|
|
52
56
|
disconnectedCallback(): void;
|
|
53
57
|
updated(changedProperties: Map<string | number | symbol, unknown>): void;
|
|
@@ -78,6 +82,11 @@ declare class EFThumbnailStrip extends LitElement {
|
|
|
78
82
|
private _onScroll;
|
|
79
83
|
private _onContextScroll;
|
|
80
84
|
private get _viewportWidth();
|
|
85
|
+
/**
|
|
86
|
+
* Watch for async content loading from child media elements.
|
|
87
|
+
* When media finishes loading, increment the epoch to invalidate cached thumbnails.
|
|
88
|
+
*/
|
|
89
|
+
private _watchChildContentLoading;
|
|
81
90
|
private _setupTargetObserver;
|
|
82
91
|
private _scheduleRender;
|
|
83
92
|
/**
|
|
@@ -86,6 +95,7 @@ declare class EFThumbnailStrip extends LitElement {
|
|
|
86
95
|
private _checkAndDispatchReady;
|
|
87
96
|
/**
|
|
88
97
|
* Calculate thumbnail layout based on current dimensions and time range.
|
|
98
|
+
* Only recreates slots if layout parameters have actually changed.
|
|
89
99
|
*/
|
|
90
100
|
private _calculateLayout;
|
|
91
101
|
/**
|
|
@@ -112,6 +122,7 @@ declare class EFThumbnailStrip extends LitElement {
|
|
|
112
122
|
private _drawThumbnailImage;
|
|
113
123
|
/**
|
|
114
124
|
* Load thumbnails that are visible in the current viewport.
|
|
125
|
+
* Skips loading if the epoch hasn't changed since last load.
|
|
115
126
|
*/
|
|
116
127
|
private _loadVisibleThumbnails;
|
|
117
128
|
/**
|
|
@@ -19,13 +19,17 @@ function isEFTimegroup(element) {
|
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Get identifiers for cache key generation.
|
|
22
|
-
* Returns rootId (for cache isolation)
|
|
22
|
+
* Returns rootId (for cache isolation), elementId (for element-specific caching), and epoch (for content versioning).
|
|
23
23
|
*/
|
|
24
24
|
function getCacheIdentifiers(element) {
|
|
25
25
|
const rootTemporal = findRootTemporal(element);
|
|
26
|
+
const rootTimegroup = rootTemporal && isEFTimegroup(rootTemporal) ? rootTemporal : null;
|
|
27
|
+
const rootId = rootTimegroup?.id || "default";
|
|
28
|
+
const epoch = rootTimegroup?.contentEpoch ?? 0;
|
|
26
29
|
return {
|
|
27
|
-
rootId
|
|
28
|
-
elementId: isEFVideo(element) ? element.src || element.id || "video" : element.id || "timegroup"
|
|
30
|
+
rootId,
|
|
31
|
+
elementId: isEFVideo(element) ? element.src || element.id || "video" : element.id || "timegroup",
|
|
32
|
+
epoch
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
35
|
/** Padding in pixels for virtual rendering (render extra thumbnails beyond viewport) */
|
|
@@ -58,6 +62,8 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
58
62
|
this._captureInProgress = false;
|
|
59
63
|
this._renderRequested = false;
|
|
60
64
|
this._hasLoadedThumbnails = false;
|
|
65
|
+
this._lastLoadedEpoch = null;
|
|
66
|
+
this._lastLayoutParams = null;
|
|
61
67
|
this._onScroll = () => {
|
|
62
68
|
if (!this._scrollContainer) return;
|
|
63
69
|
this._currentScrollLeft = this._scrollContainer.scrollLeft;
|
|
@@ -96,7 +102,11 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
96
102
|
const oldValue = this._targetElement;
|
|
97
103
|
this._targetElement = value;
|
|
98
104
|
this._mutationObserver?.disconnect();
|
|
99
|
-
if (value !== oldValue)
|
|
105
|
+
if (value !== oldValue) {
|
|
106
|
+
this._hasLoadedThumbnails = false;
|
|
107
|
+
this._lastLoadedEpoch = null;
|
|
108
|
+
this._lastLayoutParams = null;
|
|
109
|
+
}
|
|
100
110
|
if (value && value !== oldValue) this._setupTargetObserver(value);
|
|
101
111
|
this.requestUpdate("targetElement", oldValue);
|
|
102
112
|
}
|
|
@@ -222,6 +232,31 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
222
232
|
if (this._scrollContainer) return this._scrollContainer.clientWidth - this._trackLeftOffset;
|
|
223
233
|
return this._width;
|
|
224
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Watch for async content loading from child media elements.
|
|
237
|
+
* When media finishes loading, increment the epoch to invalidate cached thumbnails.
|
|
238
|
+
*/
|
|
239
|
+
_watchChildContentLoading(target) {
|
|
240
|
+
const mediaElements = target.querySelectorAll("ef-video, ef-image, ef-audio");
|
|
241
|
+
for (const el of mediaElements) {
|
|
242
|
+
const mediaEngine = el.mediaEngineTask;
|
|
243
|
+
if (mediaEngine?.taskComplete) mediaEngine.taskComplete.then(() => {
|
|
244
|
+
if (this._targetElement === target) {
|
|
245
|
+
target.incrementContentEpoch();
|
|
246
|
+
this._lastLayoutParams = null;
|
|
247
|
+
this._scheduleRender();
|
|
248
|
+
}
|
|
249
|
+
}).catch(() => {});
|
|
250
|
+
const fetchTask = el.fetchImage;
|
|
251
|
+
if (fetchTask?.taskComplete) fetchTask.taskComplete.then(() => {
|
|
252
|
+
if (this._targetElement === target) {
|
|
253
|
+
target.incrementContentEpoch();
|
|
254
|
+
this._lastLayoutParams = null;
|
|
255
|
+
this._scheduleRender();
|
|
256
|
+
}
|
|
257
|
+
}).catch(() => {});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
225
260
|
_setupTargetObserver(target) {
|
|
226
261
|
if (isEFVideo(target)) {
|
|
227
262
|
this._mutationObserver = new MutationObserver(() => this._scheduleRender());
|
|
@@ -243,11 +278,37 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
243
278
|
});
|
|
244
279
|
});
|
|
245
280
|
} else if (isEFTimegroup(target)) {
|
|
246
|
-
this._mutationObserver = new MutationObserver(() =>
|
|
281
|
+
this._mutationObserver = new MutationObserver((mutations) => {
|
|
282
|
+
if (mutations.some((mutation) => {
|
|
283
|
+
if (mutation.type === "childList") return mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0;
|
|
284
|
+
if (mutation.type === "attributes") {
|
|
285
|
+
const attrName = mutation.attributeName;
|
|
286
|
+
if (attrName === "currenttime" || attrName === "current-time" || attrName === "playing" || attrName === "loop") return false;
|
|
287
|
+
return attrName === "src" || attrName === "asset-id" || attrName === "style" || attrName === "transform";
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
})) {
|
|
291
|
+
const epochBefore = target.contentEpoch;
|
|
292
|
+
target.incrementContentEpoch();
|
|
293
|
+
if (target.contentEpoch !== epochBefore) {
|
|
294
|
+
this._lastLayoutParams = null;
|
|
295
|
+
if (mutations.some((m) => m.addedNodes.length > 0)) this._watchChildContentLoading(target);
|
|
296
|
+
this._scheduleRender();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
247
300
|
this._mutationObserver.observe(target, {
|
|
248
301
|
childList: true,
|
|
249
|
-
subtree: true
|
|
302
|
+
subtree: true,
|
|
303
|
+
attributes: true,
|
|
304
|
+
attributeFilter: [
|
|
305
|
+
"src",
|
|
306
|
+
"asset-id",
|
|
307
|
+
"style",
|
|
308
|
+
"transform"
|
|
309
|
+
]
|
|
250
310
|
});
|
|
311
|
+
this._watchChildContentLoading(target);
|
|
251
312
|
if (target.durationMs === 0) {
|
|
252
313
|
const checkDuration = () => {
|
|
253
314
|
if (this._targetElement !== target) return;
|
|
@@ -285,19 +346,32 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
285
346
|
}
|
|
286
347
|
/**
|
|
287
348
|
* Calculate thumbnail layout based on current dimensions and time range.
|
|
349
|
+
* Only recreates slots if layout parameters have actually changed.
|
|
288
350
|
*/
|
|
289
351
|
_calculateLayout() {
|
|
290
352
|
if (this._width <= 0 || this._height <= 0 || !this._targetElement) {
|
|
291
353
|
this._thumbnailSlots = [];
|
|
354
|
+
this._lastLayoutParams = null;
|
|
292
355
|
return;
|
|
293
356
|
}
|
|
294
357
|
const timeRange = this._getTimeRange();
|
|
295
358
|
if (timeRange.endMs <= timeRange.startMs) {
|
|
296
359
|
this._thumbnailSlots = [];
|
|
360
|
+
this._lastLayoutParams = null;
|
|
297
361
|
return;
|
|
298
362
|
}
|
|
299
363
|
const thumbWidth = this._getEffectiveThumbnailWidth();
|
|
300
364
|
const gap = this.gap;
|
|
365
|
+
const currentParams = {
|
|
366
|
+
width: this._width,
|
|
367
|
+
height: this._height,
|
|
368
|
+
startTimeMs: timeRange.startMs,
|
|
369
|
+
endTimeMs: timeRange.endMs,
|
|
370
|
+
thumbWidth,
|
|
371
|
+
gap
|
|
372
|
+
};
|
|
373
|
+
if (this._lastLayoutParams && this._lastLayoutParams.width === currentParams.width && this._lastLayoutParams.height === currentParams.height && this._lastLayoutParams.startTimeMs === currentParams.startTimeMs && this._lastLayoutParams.endTimeMs === currentParams.endTimeMs && this._lastLayoutParams.thumbWidth === currentParams.thumbWidth && this._lastLayoutParams.gap === currentParams.gap) return;
|
|
374
|
+
this._lastLayoutParams = currentParams;
|
|
301
375
|
const count = Math.max(1, Math.floor((this._width + gap) / (thumbWidth + gap)));
|
|
302
376
|
const pitch = count > 1 ? (this._width - thumbWidth) / (count - 1) : 0;
|
|
303
377
|
const slots = [];
|
|
@@ -355,13 +429,13 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
355
429
|
*/
|
|
356
430
|
_checkCache() {
|
|
357
431
|
if (!this._targetElement) return;
|
|
358
|
-
const { rootId, elementId } = getCacheIdentifiers(this._targetElement);
|
|
432
|
+
const { rootId, elementId, epoch } = getCacheIdentifiers(this._targetElement);
|
|
359
433
|
for (const slot of this._thumbnailSlots) {
|
|
360
|
-
const key = getCacheKey(rootId, elementId, slot.timeMs);
|
|
434
|
+
const key = getCacheKey(rootId, elementId, slot.timeMs, epoch);
|
|
361
435
|
if (sessionThumbnailCache.has(key)) {
|
|
362
436
|
slot.imageData = sessionThumbnailCache.get(key);
|
|
363
437
|
slot.status = "cached";
|
|
364
|
-
}
|
|
438
|
+
} else slot.status = "pending";
|
|
365
439
|
}
|
|
366
440
|
}
|
|
367
441
|
/**
|
|
@@ -447,9 +521,16 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
447
521
|
}
|
|
448
522
|
/**
|
|
449
523
|
* Load thumbnails that are visible in the current viewport.
|
|
524
|
+
* Skips loading if the epoch hasn't changed since last load.
|
|
450
525
|
*/
|
|
451
526
|
async _loadVisibleThumbnails() {
|
|
452
527
|
if (this._captureInProgress || !this._targetElement) return;
|
|
528
|
+
if (isEFTimegroup(this._targetElement)) {
|
|
529
|
+
const currentEpoch = this._targetElement.contentEpoch;
|
|
530
|
+
if (this._lastLoadedEpoch !== null && this._lastLoadedEpoch === currentEpoch) {
|
|
531
|
+
if (!this._thumbnailSlots.some((s) => s.status === "pending")) return;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
453
534
|
const viewportWidth = this._viewportWidth;
|
|
454
535
|
const scrollOffset = this._currentScrollLeft;
|
|
455
536
|
const stripWidth = this._width;
|
|
@@ -475,6 +556,7 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
475
556
|
} finally {
|
|
476
557
|
this._captureInProgress = false;
|
|
477
558
|
this._drawCanvas();
|
|
559
|
+
if (isEFTimegroup(this._targetElement)) this._lastLoadedEpoch = this._targetElement.contentEpoch;
|
|
478
560
|
if (this._thumbnailSlots.some((s) => s.status === "cached") && !this._hasLoadedThumbnails) {
|
|
479
561
|
this._hasLoadedThumbnails = true;
|
|
480
562
|
this.dispatchEvent(new CustomEvent("thumbnails-ready", { bubbles: true }));
|
|
@@ -486,7 +568,7 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
486
568
|
*/
|
|
487
569
|
async _captureTimegroupThumbnails(slots) {
|
|
488
570
|
const target = this._targetElement;
|
|
489
|
-
const { rootId, elementId } = getCacheIdentifiers(target);
|
|
571
|
+
const { rootId, elementId, epoch } = getCacheIdentifiers(target);
|
|
490
572
|
const timegroupWidth = target.offsetWidth || 1920;
|
|
491
573
|
const timegroupHeight = target.offsetHeight || 1080;
|
|
492
574
|
const scale = Math.min(1, this._height / timegroupHeight, MAX_CAPTURE_WIDTH / timegroupWidth);
|
|
@@ -504,7 +586,7 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
504
586
|
if (canvas) {
|
|
505
587
|
const imageData = this._canvasToImageData(canvas);
|
|
506
588
|
if (imageData) {
|
|
507
|
-
const key = getCacheKey(rootId, elementId, slot.timeMs);
|
|
589
|
+
const key = getCacheKey(rootId, elementId, slot.timeMs, epoch);
|
|
508
590
|
sessionThumbnailCache.set(key, imageData, slot.timeMs, elementId);
|
|
509
591
|
slot.imageData = imageData;
|
|
510
592
|
slot.status = "cached";
|
|
@@ -523,7 +605,7 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
523
605
|
*/
|
|
524
606
|
async _captureVideoThumbnails(slots) {
|
|
525
607
|
const target = this._targetElement;
|
|
526
|
-
const { rootId, elementId } = getCacheIdentifiers(target);
|
|
608
|
+
const { rootId, elementId, epoch } = getCacheIdentifiers(target);
|
|
527
609
|
if (target.mediaEngineTask) await target.mediaEngineTask.taskComplete;
|
|
528
610
|
const mediaEngine = target.mediaEngineTask?.value;
|
|
529
611
|
if (!mediaEngine) return;
|
|
@@ -540,7 +622,7 @@ let EFThumbnailStrip = class EFThumbnailStrip$1 extends LitElement {
|
|
|
540
622
|
if (result?.thumbnail) {
|
|
541
623
|
const imageData = this._canvasToImageData(result.thumbnail);
|
|
542
624
|
if (imageData) {
|
|
543
|
-
const key = getCacheKey(rootId, elementId, slot.timeMs);
|
|
625
|
+
const key = getCacheKey(rootId, elementId, slot.timeMs, epoch);
|
|
544
626
|
sessionThumbnailCache.set(key, imageData, slot.timeMs, elementId);
|
|
545
627
|
slot.imageData = imageData;
|
|
546
628
|
slot.status = "cached";
|