@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
package/src/gui/EFFilmstrip.ts
CHANGED
|
@@ -24,13 +24,17 @@ import {
|
|
|
24
24
|
EFCaptionsActiveWord,
|
|
25
25
|
} from "../elements/EFCaptions.js";
|
|
26
26
|
import { EFImage } from "../elements/EFImage.js";
|
|
27
|
-
import
|
|
27
|
+
import {
|
|
28
|
+
isEFTemporal,
|
|
29
|
+
type TemporalMixinInterface,
|
|
30
|
+
} from "../elements/EFTemporal.js";
|
|
28
31
|
import { EFTimegroup } from "../elements/EFTimegroup.js";
|
|
29
32
|
import { EFVideo } from "../elements/EFVideo.js";
|
|
30
33
|
import { EFWaveform } from "../elements/EFWaveform.js";
|
|
34
|
+
import { TargetController } from "../elements/TargetController.js";
|
|
31
35
|
import { TimegroupController } from "../elements/TimegroupController.js";
|
|
32
36
|
import { msToTimeCode } from "../msToTimeCode.js";
|
|
33
|
-
import {
|
|
37
|
+
import { targetTemporalContext } from "./ContextMixin.ts";
|
|
34
38
|
import type { EFPreview } from "./EFPreview.js";
|
|
35
39
|
import type { EFWorkbench } from "./EFWorkbench.js";
|
|
36
40
|
import { type FocusContext, focusContext } from "./focusContext.js";
|
|
@@ -142,9 +146,17 @@ class FilmstripItem extends TWMixin(LitElement) {
|
|
|
142
146
|
return renderFilmstripChildren(
|
|
143
147
|
Array.from(this.element.children),
|
|
144
148
|
this.pixelsPerMs,
|
|
149
|
+
this.hideSelectors,
|
|
150
|
+
this.showSelectors,
|
|
145
151
|
);
|
|
146
152
|
}
|
|
147
153
|
|
|
154
|
+
@property({ type: Array, attribute: false })
|
|
155
|
+
hideSelectors?: string[];
|
|
156
|
+
|
|
157
|
+
@property({ type: Array, attribute: false })
|
|
158
|
+
showSelectors?: string[];
|
|
159
|
+
|
|
148
160
|
contents() {
|
|
149
161
|
return html``;
|
|
150
162
|
}
|
|
@@ -295,7 +307,12 @@ export class EFCaptionsFilmstrip extends FilmstripItem {
|
|
|
295
307
|
|
|
296
308
|
renderChildren(): Array<TemplateResult<1> | typeof nothing> | typeof nothing {
|
|
297
309
|
// Also render normal DOM children (like ef-captions-active-word elements)
|
|
298
|
-
return
|
|
310
|
+
return renderFilmstripChildren(
|
|
311
|
+
Array.from(this.element.children),
|
|
312
|
+
this.pixelsPerMs,
|
|
313
|
+
this.hideSelectors,
|
|
314
|
+
this.showSelectors,
|
|
315
|
+
);
|
|
299
316
|
}
|
|
300
317
|
}
|
|
301
318
|
|
|
@@ -545,6 +562,8 @@ export class EFTimegroupFilmstrip extends FilmstripItem {
|
|
|
545
562
|
${renderFilmstripChildren(
|
|
546
563
|
Array.from(this.element.children || []),
|
|
547
564
|
this.pixelsPerMs,
|
|
565
|
+
this.hideSelectors,
|
|
566
|
+
this.showSelectors,
|
|
548
567
|
)}
|
|
549
568
|
</div>
|
|
550
569
|
`;
|
|
@@ -559,6 +578,8 @@ export class EFHTMLFilmstrip extends FilmstripItem {
|
|
|
559
578
|
${renderFilmstripChildren(
|
|
560
579
|
Array.from(this.element.children || []),
|
|
561
580
|
this.pixelsPerMs,
|
|
581
|
+
this.hideSelectors,
|
|
582
|
+
this.showSelectors,
|
|
562
583
|
)}
|
|
563
584
|
`;
|
|
564
585
|
}
|
|
@@ -578,6 +599,12 @@ class EFHierarchyItem<
|
|
|
578
599
|
@consume({ context: focusedElementContext, subscribe: true })
|
|
579
600
|
focusedElement?: HTMLElement | null;
|
|
580
601
|
|
|
602
|
+
@property({ type: Array, attribute: false })
|
|
603
|
+
hideSelectors?: string[];
|
|
604
|
+
|
|
605
|
+
@property({ type: Array, attribute: false })
|
|
606
|
+
showSelectors?: string[];
|
|
607
|
+
|
|
581
608
|
get icon(): TemplateResult<1> | string {
|
|
582
609
|
return "📼";
|
|
583
610
|
}
|
|
@@ -620,7 +647,11 @@ class EFHierarchyItem<
|
|
|
620
647
|
}
|
|
621
648
|
|
|
622
649
|
renderChildren(): Array<TemplateResult<1> | typeof nothing> | typeof nothing {
|
|
623
|
-
return renderHierarchyChildren(
|
|
650
|
+
return renderHierarchyChildren(
|
|
651
|
+
Array.from(this.element.children),
|
|
652
|
+
this.hideSelectors,
|
|
653
|
+
this.showSelectors,
|
|
654
|
+
);
|
|
624
655
|
}
|
|
625
656
|
}
|
|
626
657
|
|
|
@@ -700,50 +731,108 @@ class EFHTMLHierarchyItem extends EFHierarchyItem {
|
|
|
700
731
|
}
|
|
701
732
|
}
|
|
702
733
|
|
|
734
|
+
const shouldRenderElement = (
|
|
735
|
+
element: Element,
|
|
736
|
+
hideSelectors?: string[],
|
|
737
|
+
showSelectors?: string[],
|
|
738
|
+
): boolean => {
|
|
739
|
+
if (element instanceof HTMLElement && element.dataset?.efHidden) {
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// If show selectors are provided (allowlist mode), only render if matches
|
|
744
|
+
if (showSelectors && showSelectors.length > 0) {
|
|
745
|
+
return showSelectors.some((selector) => {
|
|
746
|
+
try {
|
|
747
|
+
return element.matches(selector);
|
|
748
|
+
} catch {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// If hide selectors are provided, don't render if matches
|
|
755
|
+
if (hideSelectors && hideSelectors.length > 0) {
|
|
756
|
+
return !hideSelectors.some((selector) => {
|
|
757
|
+
try {
|
|
758
|
+
return element.matches(selector);
|
|
759
|
+
} catch {
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// No filters, render everything
|
|
766
|
+
return true;
|
|
767
|
+
};
|
|
768
|
+
|
|
703
769
|
const renderHierarchyChildren = (
|
|
704
770
|
children: Element[],
|
|
771
|
+
hideSelectors?: string[],
|
|
772
|
+
showSelectors?: string[],
|
|
773
|
+
skipRootFiltering = false,
|
|
705
774
|
): Array<TemplateResult<1> | typeof nothing> => {
|
|
706
775
|
return children.map((child) => {
|
|
707
|
-
if (
|
|
776
|
+
if (
|
|
777
|
+
!skipRootFiltering &&
|
|
778
|
+
!shouldRenderElement(child, hideSelectors, showSelectors)
|
|
779
|
+
) {
|
|
708
780
|
return nothing;
|
|
709
781
|
}
|
|
782
|
+
|
|
710
783
|
if (child instanceof EFTimegroup) {
|
|
711
784
|
return html`<ef-timegroup-hierarchy-item
|
|
712
785
|
.element=${child}
|
|
786
|
+
.hideSelectors=${hideSelectors}
|
|
787
|
+
.showSelectors=${showSelectors}
|
|
713
788
|
></ef-timegroup-hierarchy-item>`;
|
|
714
789
|
}
|
|
715
790
|
if (child instanceof EFImage) {
|
|
716
791
|
return html`<ef-image-hierarchy-item
|
|
717
792
|
.element=${child}
|
|
793
|
+
.hideSelectors=${hideSelectors}
|
|
794
|
+
.showSelectors=${showSelectors}
|
|
718
795
|
></ef-image-hierarchy-item>`;
|
|
719
796
|
}
|
|
720
797
|
if (child instanceof EFAudio) {
|
|
721
798
|
return html`<ef-audio-hierarchy-item
|
|
722
799
|
.element=${child}
|
|
800
|
+
.hideSelectors=${hideSelectors}
|
|
801
|
+
.showSelectors=${showSelectors}
|
|
723
802
|
></ef-audio-hierarchy-item>`;
|
|
724
803
|
}
|
|
725
804
|
if (child instanceof EFVideo) {
|
|
726
805
|
return html`<ef-video-hierarchy-item
|
|
727
806
|
.element=${child}
|
|
807
|
+
.hideSelectors=${hideSelectors}
|
|
808
|
+
.showSelectors=${showSelectors}
|
|
728
809
|
></ef-video-hierarchy-item>`;
|
|
729
810
|
}
|
|
730
811
|
if (child instanceof EFCaptions) {
|
|
731
812
|
return html`<ef-captions-hierarchy-item
|
|
732
813
|
.element=${child}
|
|
814
|
+
.hideSelectors=${hideSelectors}
|
|
815
|
+
.showSelectors=${showSelectors}
|
|
733
816
|
></ef-captions-hierarchy-item>`;
|
|
734
817
|
}
|
|
735
818
|
if (child instanceof EFCaptionsActiveWord) {
|
|
736
819
|
return html`<ef-captions-active-word-hierarchy-item
|
|
737
820
|
.element=${child}
|
|
821
|
+
.hideSelectors=${hideSelectors}
|
|
822
|
+
.showSelectors=${showSelectors}
|
|
738
823
|
></ef-captions-active-word-hierarchy-item>`;
|
|
739
824
|
}
|
|
740
825
|
if (child instanceof EFWaveform) {
|
|
741
826
|
return html`<ef-waveform-hierarchy-item
|
|
742
827
|
.element=${child}
|
|
828
|
+
.hideSelectors=${hideSelectors}
|
|
829
|
+
.showSelectors=${showSelectors}
|
|
743
830
|
></ef-waveform-hierarchy-item>`;
|
|
744
831
|
}
|
|
745
832
|
return html`<ef-html-hierarchy-item
|
|
746
833
|
.element=${child}
|
|
834
|
+
.hideSelectors=${hideSelectors}
|
|
835
|
+
.showSelectors=${showSelectors}
|
|
747
836
|
></ef-html-hierarchy-item>`;
|
|
748
837
|
});
|
|
749
838
|
};
|
|
@@ -751,15 +840,24 @@ const renderHierarchyChildren = (
|
|
|
751
840
|
const renderFilmstripChildren = (
|
|
752
841
|
children: Element[],
|
|
753
842
|
pixelsPerMs: number,
|
|
843
|
+
hideSelectors?: string[],
|
|
844
|
+
showSelectors?: string[],
|
|
845
|
+
skipRootFiltering = false,
|
|
754
846
|
): Array<TemplateResult<1> | typeof nothing> => {
|
|
755
847
|
return children.map((child) => {
|
|
756
|
-
if (
|
|
848
|
+
if (
|
|
849
|
+
!skipRootFiltering &&
|
|
850
|
+
!shouldRenderElement(child, hideSelectors, showSelectors)
|
|
851
|
+
) {
|
|
757
852
|
return nothing;
|
|
758
853
|
}
|
|
854
|
+
|
|
759
855
|
if (child instanceof EFTimegroup) {
|
|
760
856
|
return html`<ef-timegroup-filmstrip
|
|
761
857
|
.element=${child}
|
|
762
858
|
.pixelsPerMs=${pixelsPerMs}
|
|
859
|
+
.hideSelectors=${hideSelectors}
|
|
860
|
+
.showSelectors=${showSelectors}
|
|
763
861
|
>
|
|
764
862
|
</ef-timegroup-filmstrip>`;
|
|
765
863
|
}
|
|
@@ -767,59 +865,79 @@ const renderFilmstripChildren = (
|
|
|
767
865
|
return html`<ef-image-filmstrip
|
|
768
866
|
.element=${child}
|
|
769
867
|
.pixelsPerMs=${pixelsPerMs}
|
|
868
|
+
.hideSelectors=${hideSelectors}
|
|
869
|
+
.showSelectors=${showSelectors}
|
|
770
870
|
></ef-image-filmstrip>`;
|
|
771
871
|
}
|
|
772
872
|
if (child instanceof EFAudio) {
|
|
773
873
|
return html`<ef-audio-filmstrip
|
|
774
874
|
.element=${child}
|
|
775
875
|
.pixelsPerMs=${pixelsPerMs}
|
|
876
|
+
.hideSelectors=${hideSelectors}
|
|
877
|
+
.showSelectors=${showSelectors}
|
|
776
878
|
></ef-audio-filmstrip>`;
|
|
777
879
|
}
|
|
778
880
|
if (child instanceof EFVideo) {
|
|
779
881
|
return html`<ef-video-filmstrip
|
|
780
882
|
.element=${child}
|
|
781
883
|
.pixelsPerMs=${pixelsPerMs}
|
|
884
|
+
.hideSelectors=${hideSelectors}
|
|
885
|
+
.showSelectors=${showSelectors}
|
|
782
886
|
></ef-video-filmstrip>`;
|
|
783
887
|
}
|
|
784
888
|
if (child instanceof EFCaptions) {
|
|
785
889
|
return html`<ef-captions-filmstrip
|
|
786
890
|
.element=${child}
|
|
787
891
|
.pixelsPerMs=${pixelsPerMs}
|
|
892
|
+
.hideSelectors=${hideSelectors}
|
|
893
|
+
.showSelectors=${showSelectors}
|
|
788
894
|
></ef-captions-filmstrip>`;
|
|
789
895
|
}
|
|
790
896
|
if (child instanceof EFCaptionsActiveWord) {
|
|
791
897
|
return html`<ef-captions-active-word-filmstrip
|
|
792
898
|
.element=${child}
|
|
793
899
|
.pixelsPerMs=${pixelsPerMs}
|
|
900
|
+
.hideSelectors=${hideSelectors}
|
|
901
|
+
.showSelectors=${showSelectors}
|
|
794
902
|
></ef-captions-active-word-filmstrip>`;
|
|
795
903
|
}
|
|
796
904
|
if (child.tagName === "EF-CAPTIONS-SEGMENT") {
|
|
797
905
|
return html`<ef-captions-segment-filmstrip
|
|
798
906
|
.element=${child}
|
|
799
907
|
.pixelsPerMs=${pixelsPerMs}
|
|
908
|
+
.hideSelectors=${hideSelectors}
|
|
909
|
+
.showSelectors=${showSelectors}
|
|
800
910
|
></ef-captions-segment-filmstrip>`;
|
|
801
911
|
}
|
|
802
912
|
if (child.tagName === "EF-CAPTIONS-BEFORE-ACTIVE-WORD") {
|
|
803
913
|
return html`<ef-captions-before-word-filmstrip
|
|
804
914
|
.element=${child}
|
|
805
915
|
.pixelsPerMs=${pixelsPerMs}
|
|
916
|
+
.hideSelectors=${hideSelectors}
|
|
917
|
+
.showSelectors=${showSelectors}
|
|
806
918
|
></ef-captions-before-word-filmstrip>`;
|
|
807
919
|
}
|
|
808
920
|
if (child.tagName === "EF-CAPTIONS-AFTER-ACTIVE-WORD") {
|
|
809
921
|
return html`<ef-captions-after-word-filmstrip
|
|
810
922
|
.element=${child}
|
|
811
923
|
.pixelsPerMs=${pixelsPerMs}
|
|
924
|
+
.hideSelectors=${hideSelectors}
|
|
925
|
+
.showSelectors=${showSelectors}
|
|
812
926
|
></ef-captions-after-word-filmstrip>`;
|
|
813
927
|
}
|
|
814
928
|
if (child instanceof EFWaveform) {
|
|
815
929
|
return html`<ef-waveform-filmstrip
|
|
816
930
|
.element=${child}
|
|
817
931
|
.pixelsPerMs=${pixelsPerMs}
|
|
932
|
+
.hideSelectors=${hideSelectors}
|
|
933
|
+
.showSelectors=${showSelectors}
|
|
818
934
|
></ef-waveform-filmstrip>`;
|
|
819
935
|
}
|
|
820
936
|
return html`<ef-html-filmstrip
|
|
821
937
|
.element=${child}
|
|
822
938
|
.pixelsPerMs=${pixelsPerMs}
|
|
939
|
+
.hideSelectors=${hideSelectors}
|
|
940
|
+
.showSelectors=${showSelectors}
|
|
823
941
|
></ef-html-filmstrip>`;
|
|
824
942
|
});
|
|
825
943
|
};
|
|
@@ -839,6 +957,28 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
839
957
|
@property({ type: Number })
|
|
840
958
|
pixelsPerMs = 0.04;
|
|
841
959
|
|
|
960
|
+
@property({ type: String })
|
|
961
|
+
hide = "";
|
|
962
|
+
|
|
963
|
+
@property({ type: String })
|
|
964
|
+
show = "";
|
|
965
|
+
|
|
966
|
+
get hideSelectors(): string[] | undefined {
|
|
967
|
+
if (!this.hide) return undefined;
|
|
968
|
+
return this.hide
|
|
969
|
+
.split(",")
|
|
970
|
+
.map((s) => s.trim())
|
|
971
|
+
.filter((s) => s.length > 0);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
get showSelectors(): string[] | undefined {
|
|
975
|
+
if (!this.show) return undefined;
|
|
976
|
+
return this.show
|
|
977
|
+
.split(",")
|
|
978
|
+
.map((s) => s.trim())
|
|
979
|
+
.filter((s) => s.length > 0);
|
|
980
|
+
}
|
|
981
|
+
|
|
842
982
|
@state()
|
|
843
983
|
scrubbing = false;
|
|
844
984
|
|
|
@@ -873,6 +1013,10 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
873
1013
|
window.addEventListener("keypress", this.#handleKeyPress);
|
|
874
1014
|
|
|
875
1015
|
this.resizeObserver.observe(this);
|
|
1016
|
+
|
|
1017
|
+
if (this.target) {
|
|
1018
|
+
this.#targetController = new TargetController(this);
|
|
1019
|
+
}
|
|
876
1020
|
}
|
|
877
1021
|
|
|
878
1022
|
disconnectedCallback(): void {
|
|
@@ -882,7 +1026,7 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
882
1026
|
}
|
|
883
1027
|
|
|
884
1028
|
updatePixelsPerMs() {
|
|
885
|
-
const target = this.
|
|
1029
|
+
const target = this.targetTemporal;
|
|
886
1030
|
const gutter = this.gutterRef.value;
|
|
887
1031
|
if (target && gutter && gutter.clientWidth > 0) {
|
|
888
1032
|
this.pixelsPerMs = gutter.clientWidth / (target.durationMs || 1);
|
|
@@ -893,9 +1037,12 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
893
1037
|
if (this.timegroupController) {
|
|
894
1038
|
this.timegroupController.remove();
|
|
895
1039
|
}
|
|
896
|
-
const target = this.
|
|
1040
|
+
const target = this.targetTemporal;
|
|
897
1041
|
if (target) {
|
|
898
|
-
this.timegroupController = new TimegroupController(
|
|
1042
|
+
this.timegroupController = new TimegroupController(
|
|
1043
|
+
target as EFTimegroup,
|
|
1044
|
+
this,
|
|
1045
|
+
);
|
|
899
1046
|
// Set the current time to the last saved time to avoid a cycle
|
|
900
1047
|
// where the filmstrip clobbers the time loaded from localStorage
|
|
901
1048
|
this.currentTimeMs = target.currentTimeMs;
|
|
@@ -975,16 +1122,16 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
975
1122
|
return;
|
|
976
1123
|
}
|
|
977
1124
|
const rect = gutter.getBoundingClientRect();
|
|
978
|
-
if (this.
|
|
1125
|
+
if (this.targetTemporal) {
|
|
979
1126
|
const layerX = e.pageX - rect.left + gutter.scrollLeft;
|
|
980
1127
|
const scrubTimeMs = layerX / this.pixelsPerMs;
|
|
981
|
-
this.
|
|
1128
|
+
this.targetTemporal.currentTimeMs = scrubTimeMs;
|
|
982
1129
|
}
|
|
983
1130
|
}
|
|
984
1131
|
|
|
985
1132
|
@eventOptions({ passive: false })
|
|
986
1133
|
scrollScrub(e: WheelEvent) {
|
|
987
|
-
if (this.
|
|
1134
|
+
if (this.targetTemporal && this.gutter && !this.playing) {
|
|
988
1135
|
if (e.deltaX !== 0) {
|
|
989
1136
|
e.preventDefault(); // Prevent default side scroll behavior only
|
|
990
1137
|
}
|
|
@@ -1010,7 +1157,7 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
1010
1157
|
|
|
1011
1158
|
if (this) {
|
|
1012
1159
|
this.gutter.scrollBy(e.deltaX, e.deltaY);
|
|
1013
|
-
this.
|
|
1160
|
+
this.targetTemporal.currentTimeMs += e.deltaX / this.pixelsPerMs;
|
|
1014
1161
|
}
|
|
1015
1162
|
}
|
|
1016
1163
|
}
|
|
@@ -1024,7 +1171,7 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
1024
1171
|
}
|
|
1025
1172
|
|
|
1026
1173
|
render() {
|
|
1027
|
-
const target = this.
|
|
1174
|
+
const target = this.targetTemporal;
|
|
1028
1175
|
|
|
1029
1176
|
return html` <div
|
|
1030
1177
|
class="grid h-full bg-slate-100"
|
|
@@ -1068,7 +1215,12 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
1068
1215
|
${ref(this.hierarchyRef)}
|
|
1069
1216
|
@scroll=${this.syncHierarchyScroll}
|
|
1070
1217
|
>
|
|
1071
|
-
${renderHierarchyChildren(
|
|
1218
|
+
${renderHierarchyChildren(
|
|
1219
|
+
target ? ([target] as unknown as Element[]) : [],
|
|
1220
|
+
this.hideSelectors,
|
|
1221
|
+
this.showSelectors,
|
|
1222
|
+
true,
|
|
1223
|
+
)}
|
|
1072
1224
|
</div>
|
|
1073
1225
|
<div
|
|
1074
1226
|
class="flex h-full w-full cursor-crosshair overflow-auto bg-slate-200 pt-[8px]"
|
|
@@ -1092,19 +1244,25 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
1092
1244
|
${ref(this.playheadRef)}
|
|
1093
1245
|
></div>
|
|
1094
1246
|
|
|
1095
|
-
${renderFilmstripChildren(
|
|
1247
|
+
${renderFilmstripChildren(
|
|
1248
|
+
target ? ([target] as unknown as Element[]) : [],
|
|
1249
|
+
this.pixelsPerMs,
|
|
1250
|
+
this.hideSelectors,
|
|
1251
|
+
this.showSelectors,
|
|
1252
|
+
true,
|
|
1253
|
+
)}
|
|
1096
1254
|
</div>
|
|
1097
1255
|
</div>
|
|
1098
1256
|
</div>`;
|
|
1099
1257
|
}
|
|
1100
1258
|
|
|
1101
1259
|
updated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>) {
|
|
1102
|
-
if (!this.
|
|
1260
|
+
if (!this.targetTemporal) {
|
|
1103
1261
|
return;
|
|
1104
1262
|
}
|
|
1105
1263
|
if (changes.has("currentTimeMs")) {
|
|
1106
|
-
if (this.
|
|
1107
|
-
this.
|
|
1264
|
+
if (this.targetTemporal.currentTimeMs !== this.currentTimeMs) {
|
|
1265
|
+
this.targetTemporal.currentTimeMs = this.currentTimeMs;
|
|
1108
1266
|
}
|
|
1109
1267
|
}
|
|
1110
1268
|
}
|
|
@@ -1114,18 +1272,50 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
1114
1272
|
}
|
|
1115
1273
|
|
|
1116
1274
|
@property({ type: String })
|
|
1117
|
-
target
|
|
1275
|
+
target = "";
|
|
1276
|
+
|
|
1277
|
+
@state()
|
|
1278
|
+
targetElement: Element | null = null;
|
|
1118
1279
|
|
|
1119
|
-
|
|
1280
|
+
#targetController?: TargetController;
|
|
1281
|
+
#lastTargetTemporal?: TemporalMixinInterface | null;
|
|
1282
|
+
|
|
1283
|
+
@consume({ context: targetTemporalContext, subscribe: true })
|
|
1120
1284
|
@state()
|
|
1121
|
-
|
|
1285
|
+
private _contextProvidedTemporal?: TemporalMixinInterface | null;
|
|
1286
|
+
|
|
1287
|
+
get targetTemporal(): TemporalMixinInterface | null {
|
|
1288
|
+
const fromTarget =
|
|
1289
|
+
this.targetElement && isEFTemporal(this.targetElement)
|
|
1290
|
+
? (this.targetElement as TemporalMixinInterface & HTMLElement)
|
|
1291
|
+
: null;
|
|
1292
|
+
const fromContext = this._contextProvidedTemporal;
|
|
1293
|
+
|
|
1294
|
+
if (fromTarget && fromContext && fromTarget !== fromContext) {
|
|
1295
|
+
console.warn(
|
|
1296
|
+
"EFFilmstrip: Both target attribute and parent context found. Using target attribute.",
|
|
1297
|
+
{ target: this.target, fromTarget, fromContext },
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
return fromTarget ?? fromContext ?? null;
|
|
1302
|
+
}
|
|
1122
1303
|
|
|
1123
1304
|
protected willUpdate(
|
|
1124
1305
|
changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
|
|
1125
1306
|
) {
|
|
1126
|
-
if (changedProperties.has("
|
|
1307
|
+
if (changedProperties.has("target")) {
|
|
1308
|
+
if (this.target && !this.#targetController) {
|
|
1309
|
+
this.#targetController = new TargetController(this);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
const currentTargetTemporal = this.targetTemporal;
|
|
1314
|
+
if (this.#lastTargetTemporal !== currentTargetTemporal) {
|
|
1127
1315
|
this.#bindToTargetTimegroup();
|
|
1316
|
+
this.#lastTargetTemporal = currentTargetTemporal;
|
|
1128
1317
|
}
|
|
1318
|
+
|
|
1129
1319
|
if (this.autoScale) {
|
|
1130
1320
|
this.updatePixelsPerMs();
|
|
1131
1321
|
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { html, render } from "lit";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
import "../elements/EFTimegroup.js";
|
|
5
|
+
import "../elements/EFVideo.js";
|
|
6
|
+
import "./EFConfiguration.js";
|
|
7
|
+
import "./EFPause.js";
|
|
8
|
+
import "./EFPreview.js";
|
|
9
|
+
|
|
10
|
+
describe("EFPause", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
while (document.body.children.length) {
|
|
13
|
+
document.body.children[0]?.remove();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
const elements = document.querySelectorAll("ef-pause");
|
|
19
|
+
for (const element of elements) {
|
|
20
|
+
element.remove();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("should be defined", () => {
|
|
25
|
+
const element = document.createElement("ef-pause");
|
|
26
|
+
expect(element).toBeDefined();
|
|
27
|
+
expect(element.tagName).toBe("EF-PAUSE");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("should be hidden when not playing", async () => {
|
|
31
|
+
const container = document.createElement("div");
|
|
32
|
+
render(
|
|
33
|
+
html`
|
|
34
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
35
|
+
<ef-preview id="test-preview">
|
|
36
|
+
<ef-video src="bars-n-tone.mp4"></ef-video>
|
|
37
|
+
<ef-pause>Pause Button</ef-pause>
|
|
38
|
+
</ef-preview>
|
|
39
|
+
</ef-configuration>
|
|
40
|
+
`,
|
|
41
|
+
container,
|
|
42
|
+
);
|
|
43
|
+
document.body.appendChild(container);
|
|
44
|
+
|
|
45
|
+
const pause = container.querySelector("ef-pause") as any;
|
|
46
|
+
const preview = container.querySelector("ef-preview") as any;
|
|
47
|
+
const video = container.querySelector("ef-video") as any;
|
|
48
|
+
|
|
49
|
+
await pause.updateComplete;
|
|
50
|
+
await preview.updateComplete;
|
|
51
|
+
await video.updateComplete;
|
|
52
|
+
|
|
53
|
+
await video.mediaEngineTask.run();
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
55
|
+
await pause.updateComplete;
|
|
56
|
+
|
|
57
|
+
expect(pause.playing).toBe(false);
|
|
58
|
+
expect(getComputedStyle(pause).display).toBe("none");
|
|
59
|
+
|
|
60
|
+
container.remove();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("should be visible when playing", async () => {
|
|
64
|
+
const container = document.createElement("div");
|
|
65
|
+
render(
|
|
66
|
+
html`
|
|
67
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
68
|
+
<ef-preview id="test-preview">
|
|
69
|
+
<ef-video src="bars-n-tone.mp4"></ef-video>
|
|
70
|
+
<ef-pause>Pause Button</ef-pause>
|
|
71
|
+
</ef-preview>
|
|
72
|
+
</ef-configuration>
|
|
73
|
+
`,
|
|
74
|
+
container,
|
|
75
|
+
);
|
|
76
|
+
document.body.appendChild(container);
|
|
77
|
+
|
|
78
|
+
const pause = container.querySelector("ef-pause") as any;
|
|
79
|
+
const preview = container.querySelector("ef-preview") as any;
|
|
80
|
+
const video = container.querySelector("ef-video") as any;
|
|
81
|
+
|
|
82
|
+
await pause.updateComplete;
|
|
83
|
+
await preview.updateComplete;
|
|
84
|
+
await video.updateComplete;
|
|
85
|
+
|
|
86
|
+
await video.mediaEngineTask.run();
|
|
87
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
88
|
+
await pause.updateComplete;
|
|
89
|
+
|
|
90
|
+
expect(getComputedStyle(pause).display).toBe("none");
|
|
91
|
+
|
|
92
|
+
// Manually trigger playing state change to test visibility mechanism
|
|
93
|
+
pause.playing = true;
|
|
94
|
+
await pause.updateComplete;
|
|
95
|
+
|
|
96
|
+
expect(getComputedStyle(pause).display).not.toBe("none");
|
|
97
|
+
|
|
98
|
+
container.remove();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("should call pause() when clicked", async () => {
|
|
102
|
+
const container = document.createElement("div");
|
|
103
|
+
render(
|
|
104
|
+
html`
|
|
105
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
106
|
+
<ef-preview id="test-preview">
|
|
107
|
+
<ef-video src="bars-n-tone.mp4"></ef-video>
|
|
108
|
+
<ef-pause>Pause Button</ef-pause>
|
|
109
|
+
</ef-preview>
|
|
110
|
+
</ef-configuration>
|
|
111
|
+
`,
|
|
112
|
+
container,
|
|
113
|
+
);
|
|
114
|
+
document.body.appendChild(container);
|
|
115
|
+
|
|
116
|
+
const pause = container.querySelector("ef-pause") as any;
|
|
117
|
+
const preview = container.querySelector("ef-preview") as any;
|
|
118
|
+
const video = container.querySelector("ef-video") as any;
|
|
119
|
+
|
|
120
|
+
await pause.updateComplete;
|
|
121
|
+
await preview.updateComplete;
|
|
122
|
+
await video.updateComplete;
|
|
123
|
+
|
|
124
|
+
await video.mediaEngineTask.run();
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
126
|
+
await pause.updateComplete;
|
|
127
|
+
|
|
128
|
+
const pauseSpy = vi.spyOn(video.playbackController, "pause");
|
|
129
|
+
|
|
130
|
+
pause.click();
|
|
131
|
+
|
|
132
|
+
expect(pauseSpy).toHaveBeenCalledTimes(1);
|
|
133
|
+
|
|
134
|
+
pauseSpy.mockRestore();
|
|
135
|
+
container.remove();
|
|
136
|
+
}, 1000);
|
|
137
|
+
|
|
138
|
+
test("should pass through children with default slot", async () => {
|
|
139
|
+
const container = document.createElement("div");
|
|
140
|
+
render(
|
|
141
|
+
html`
|
|
142
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
143
|
+
<ef-preview id="test-preview">
|
|
144
|
+
<ef-video src="bars-n-tone.mp4"></ef-video>
|
|
145
|
+
<ef-pause><span id="pause-content">⏸ Pause</span></ef-pause>
|
|
146
|
+
</ef-preview>
|
|
147
|
+
</ef-configuration>
|
|
148
|
+
`,
|
|
149
|
+
container,
|
|
150
|
+
);
|
|
151
|
+
document.body.appendChild(container);
|
|
152
|
+
|
|
153
|
+
const pause = container.querySelector("ef-pause") as any;
|
|
154
|
+
const content = container.querySelector("#pause-content");
|
|
155
|
+
|
|
156
|
+
await pause.updateComplete;
|
|
157
|
+
|
|
158
|
+
expect(content).toBeDefined();
|
|
159
|
+
expect(content?.textContent).toBe("⏸ Pause");
|
|
160
|
+
|
|
161
|
+
container.remove();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("should work with target attribute", async () => {
|
|
165
|
+
const container = document.createElement("div");
|
|
166
|
+
render(
|
|
167
|
+
html`
|
|
168
|
+
<ef-configuration api-host="http://localhost:63315" signing-url="">
|
|
169
|
+
<ef-preview id="test-preview">
|
|
170
|
+
<ef-video src="bars-n-tone.mp4"></ef-video>
|
|
171
|
+
</ef-preview>
|
|
172
|
+
<ef-pause target="test-preview">Pause Button</ef-pause>
|
|
173
|
+
</ef-configuration>
|
|
174
|
+
`,
|
|
175
|
+
container,
|
|
176
|
+
);
|
|
177
|
+
document.body.appendChild(container);
|
|
178
|
+
|
|
179
|
+
const pause = container.querySelector("ef-pause") as any;
|
|
180
|
+
const preview = container.querySelector("ef-preview") as any;
|
|
181
|
+
const video = container.querySelector("ef-video") as any;
|
|
182
|
+
|
|
183
|
+
await pause.updateComplete;
|
|
184
|
+
await preview.updateComplete;
|
|
185
|
+
await video.updateComplete;
|
|
186
|
+
|
|
187
|
+
await video.mediaEngineTask.run();
|
|
188
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
189
|
+
await pause.updateComplete;
|
|
190
|
+
|
|
191
|
+
expect(pause.efContext).toBe(preview);
|
|
192
|
+
|
|
193
|
+
const pauseSpy = vi.spyOn(video.playbackController, "pause");
|
|
194
|
+
|
|
195
|
+
pause.click();
|
|
196
|
+
|
|
197
|
+
expect(pauseSpy).toHaveBeenCalledTimes(1);
|
|
198
|
+
|
|
199
|
+
pauseSpy.mockRestore();
|
|
200
|
+
container.remove();
|
|
201
|
+
}, 1000);
|
|
202
|
+
});
|