movi-player 0.3.1 → 0.3.2
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/AGENTS.md +2 -0
- package/README.md +2 -0
- package/dist/decode/VideoDecoder.d.ts.map +1 -1
- package/dist/decode/VideoDecoder.js +6 -2
- package/dist/decode/VideoDecoder.js.map +1 -1
- package/dist/demuxer.cjs +1 -1
- package/dist/demuxer.js +73 -73
- package/dist/element.cjs +38 -37
- package/dist/element.js +38 -37
- package/dist/index.cjs +38 -37
- package/dist/index.js +38 -37
- package/dist/player.cjs +1 -1
- package/dist/player.js +1 -1
- package/dist/render/MoviElement.d.ts +1 -0
- package/dist/render/MoviElement.d.ts.map +1 -1
- package/dist/render/MoviElement.js +68 -34
- package/dist/render/MoviElement.js.map +1 -1
- package/package.json +10 -2
package/dist/element.cjs
CHANGED
|
@@ -49950,7 +49950,7 @@ class MoviVideoDecoder {
|
|
|
49950
49950
|
}
|
|
49951
49951
|
async configure(A, v, b = 0) {
|
|
49952
49952
|
if (this.currentTrack = A, this.targetFps = b, this.currentProfile = A.profile, this.useSoftware = false, this.requiresSoftware = false, this.isAnnexBSource = false, this.openGopErrorCount = 0, this.hardwareRetryCount = 0, this.lastHardwareRetryTime = 0, this.swDecoder && (this.swDecoder.close(), this.swDecoder = null), this.forceSoftware) return Logger$1.info(TAG$h, "Force software decoding enabled, using WASM decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49953
|
-
if (!("VideoDecoder" in window)) return Logger$1.
|
|
49953
|
+
if (!("VideoDecoder" in window)) return Logger$1.warn(TAG$h, "WebCodecs VideoDecoder not supported — falling back to software decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49954
49954
|
let j = CodecParser.getCodecString(A.codec, A.extradata);
|
|
49955
49955
|
if (j || (Logger$1.debug(TAG$h, "CodecParser returned null, falling back to manual mapping"), j = this.mapCodecToWebCodecs(A.codec, A.width, A.height, A.profile, A.level)), !j) return Logger$1.error(TAG$h, `Unsupported codec: ${A.codec}`), false;
|
|
49956
49956
|
const s2 = { codec: j, codedWidth: A.width, codedHeight: A.height, hardwareAcceleration: "prefer-hardware" };
|
|
@@ -108886,6 +108886,7 @@ class MoviElement extends HTMLElement {
|
|
|
108886
108886
|
isOverControls = false;
|
|
108887
108887
|
isSeeking = false;
|
|
108888
108888
|
pendingSeekTarget = null;
|
|
108889
|
+
_pendingSeek = null;
|
|
108889
108890
|
isDragging = false;
|
|
108890
108891
|
isTouchDragging = false;
|
|
108891
108892
|
touchStartX = 0;
|
|
@@ -109011,7 +109012,7 @@ class MoviElement extends HTMLElement {
|
|
|
109011
109012
|
return ["src", "autoplay", "controls", "loop", "muted", "playsinline", "preload", "poster", "width", "height", "crossorigin", "volume", "playbackrate", "subtitledelay", "subtitlesize", "subtitlecolor", "subtitlebg", "subtitleedge", "ambientmode", "ambientwrapper", "renderer", "objectfit", "thumb", "hdr", "theme", "sw", "fps", "gesturefs", "nohotkeys", "startat", "fastseek", "doubletap", "themecolor", "buffersize", "title", "showtitle", "resume", "stablevolume", "encrypted", "tokenurl", "videourl", "videoid", "drm", "licenseurl", "licenseheaders", "headers", "audioonly", "lcevc", "lcevcurl", "postertime"];
|
|
109012
109013
|
}
|
|
109013
109014
|
constructor() {
|
|
109014
|
-
super(),
|
|
109015
|
+
super(), Logger$1.setLevel(LogLevel.DEBUG);
|
|
109015
109016
|
const A = this.attachShadow({ mode: "open" });
|
|
109016
109017
|
this.canvas = document.createElement("canvas"), this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.display = "block", this.canvas.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), A.appendChild(this.canvas), this.video = document.createElement("video"), this.video.style.width = "100%", this.video.style.height = "100%", this.video.style.display = "none", this.video.style.objectFit = "contain", this.video.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), A.appendChild(this.video), this.posterElement = document.createElement("img"), this.posterElement.className = "movi-poster-overlay", this.posterElement.crossOrigin = "anonymous", this.posterElement.referrerPolicy = "no-referrer", this.posterElement.decoding = "async", this.posterElement.addEventListener("error", () => {
|
|
109017
109018
|
const A2 = this.posterElement.src.match(/\/vi\/([\w-]+)\/maxresdefault\.jpg/);
|
|
@@ -110878,6 +110879,7 @@ class MoviElement extends HTMLElement {
|
|
|
110878
110879
|
const A2 = this.player?.getState();
|
|
110879
110880
|
"playing" !== A2 && "buffering" !== A2 && b.classList.add("movi-center-visible");
|
|
110880
110881
|
}
|
|
110882
|
+
this._hasEverPlayed ? this.classList.add("movi-bar-visible") : this.classList.remove("movi-bar-visible");
|
|
110881
110883
|
const E = this.shadowRoot?.querySelector(".movi-controls-bar"), F = E?.offsetHeight ?? 80, k = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
110882
110884
|
let x = F + 20;
|
|
110883
110885
|
if (k && "none" !== k.style.display ? (k.style.bottom = `${F + 20}px`, requestAnimationFrame(() => {
|
|
@@ -110967,7 +110969,7 @@ class MoviElement extends HTMLElement {
|
|
|
110967
110969
|
b2 && (b2.style.cursor = "none");
|
|
110968
110970
|
}
|
|
110969
110971
|
const v = this.shadowRoot?.querySelector(".movi-center-play-pause"), b = this.player?.getState();
|
|
110970
|
-
v && "playing" === b && v.classList.remove("movi-center-visible");
|
|
110972
|
+
v && "playing" === b && v.classList.remove("movi-center-visible"), this.classList.remove("movi-bar-visible");
|
|
110971
110973
|
const j = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
110972
110974
|
if (j && (j.style.bottom = "12px"), this.player && (j && "none" !== j.style.display ? requestAnimationFrame(() => {
|
|
110973
110975
|
const A2 = j.offsetHeight || 0;
|
|
@@ -111149,6 +111151,14 @@ class MoviElement extends HTMLElement {
|
|
|
111149
111151
|
-moz-osx-font-smoothing: grayscale;
|
|
111150
111152
|
}
|
|
111151
111153
|
|
|
111154
|
+
/* The :host{display:block} above is an author rule, so it beats the
|
|
111155
|
+
UA stylesheet's [hidden]{display:none}. Without this, the standard
|
|
111156
|
+
hidden attribute does nothing and the player stays visible. Honour
|
|
111157
|
+
it explicitly. !important so source-order/specificity can't regress it. */
|
|
111158
|
+
:host([hidden]) {
|
|
111159
|
+
display: none !important;
|
|
111160
|
+
}
|
|
111161
|
+
|
|
111152
111162
|
/* Light Theme Override */
|
|
111153
111163
|
:host([theme="light"]) {
|
|
111154
111164
|
--movi-primary: #7c3aed; /* Vibrancy boost for light theme */
|
|
@@ -113737,12 +113747,13 @@ class MoviElement extends HTMLElement {
|
|
|
113737
113747
|
height: 64px !important;
|
|
113738
113748
|
}
|
|
113739
113749
|
|
|
113740
|
-
/*
|
|
113750
|
+
/* Keyframe animations off on small/compact layouts for perf, but keep
|
|
113751
|
+
CSS transitions so the controls + centre button still move smoothly
|
|
113752
|
+
here too (the PiP / mini player is a small container). */
|
|
113741
113753
|
.movi-controls-overlay,
|
|
113742
113754
|
.movi-center-play-pause,
|
|
113743
113755
|
.movi-btn,
|
|
113744
113756
|
.movi-progress-handle {
|
|
113745
|
-
transition: none !important;
|
|
113746
113757
|
animation: none !important;
|
|
113747
113758
|
transform: none !important;
|
|
113748
113759
|
}
|
|
@@ -114234,7 +114245,7 @@ class MoviElement extends HTMLElement {
|
|
|
114234
114245
|
button's bar-hidden and both-bars-visible rules exactly. */
|
|
114235
114246
|
.movi-loading-indicator {
|
|
114236
114247
|
position: absolute;
|
|
114237
|
-
top:
|
|
114248
|
+
top: 50%;
|
|
114238
114249
|
left: 50%;
|
|
114239
114250
|
transform: translate(-50%, -50%);
|
|
114240
114251
|
display: flex;
|
|
@@ -114243,15 +114254,7 @@ class MoviElement extends HTMLElement {
|
|
|
114243
114254
|
z-index: 1000;
|
|
114244
114255
|
pointer-events: none;
|
|
114245
114256
|
background: transparent;
|
|
114246
|
-
|
|
114247
|
-
|
|
114248
|
-
:host:has(.movi-controls-container.movi-controls-hidden) .movi-loading-indicator,
|
|
114249
|
-
:host(:not([controls])) .movi-loading-indicator {
|
|
114250
|
-
top: 50%;
|
|
114251
|
-
}
|
|
114252
|
-
|
|
114253
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-loading-indicator {
|
|
114254
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114257
|
+
transition: top var(--movi-transition-normal);
|
|
114255
114258
|
}
|
|
114256
114259
|
|
|
114257
114260
|
.movi-loader-container {
|
|
@@ -114293,7 +114296,7 @@ class MoviElement extends HTMLElement {
|
|
|
114293
114296
|
down adjust this for the other two layout states. */
|
|
114294
114297
|
.movi-center-play-pause {
|
|
114295
114298
|
position: absolute;
|
|
114296
|
-
top:
|
|
114299
|
+
top: 50%;
|
|
114297
114300
|
left: 50%;
|
|
114298
114301
|
transform: translate(-50%, -50%) scale(0.8);
|
|
114299
114302
|
z-index: 5;
|
|
@@ -114322,23 +114325,15 @@ class MoviElement extends HTMLElement {
|
|
|
114322
114325
|
transition-delay: 0s;
|
|
114323
114326
|
}
|
|
114324
114327
|
|
|
114325
|
-
/*
|
|
114326
|
-
|
|
114327
|
-
|
|
114328
|
-
|
|
114329
|
-
|
|
114330
|
-
|
|
114331
|
-
|
|
114332
|
-
|
|
114333
|
-
|
|
114334
|
-
top), not the full player. The 44% default biases too far up
|
|
114335
|
-
when there's also a title bar to balance the controls; here
|
|
114336
|
-
the offset is just half the *difference* between the two
|
|
114337
|
-
chrome heights (title ≈ 52px, controls 72px → ~10px above
|
|
114338
|
-
centre on desktop). calc() keeps it right on mobile where
|
|
114339
|
-
--movi-controls-height drops to 64px too. */
|
|
114340
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-center-play-pause {
|
|
114341
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114328
|
+
/* Default (the base rule) is the true geometric centre. When the controls
|
|
114329
|
+
bar is visible, lift the centre button AND the loading spinner a little
|
|
114330
|
+
so they read as centred in the band above the bar. Keyed off a host
|
|
114331
|
+
class toggled in show/hideControls, because :host:has() checks against
|
|
114332
|
+
the shadow tree don't apply in every engine (notably Electron). The
|
|
114333
|
+
transition on top (in each base rule) animates the move. */
|
|
114334
|
+
:host(.movi-bar-visible) .movi-center-play-pause,
|
|
114335
|
+
:host(.movi-bar-visible) .movi-loading-indicator {
|
|
114336
|
+
top: calc(50% - var(--movi-controls-height) / 4);
|
|
114342
114337
|
}
|
|
114343
114338
|
|
|
114344
114339
|
.movi-center-play-pause:hover {
|
|
@@ -115937,6 +115932,7 @@ class MoviElement extends HTMLElement {
|
|
|
115937
115932
|
});
|
|
115938
115933
|
};
|
|
115939
115934
|
connectedCallback() {
|
|
115935
|
+
this.hasAttribute("tabindex") || (this.tabIndex = 0);
|
|
115940
115936
|
const A = this.getAttribute("src");
|
|
115941
115937
|
this._src = A || null, this._autoplay = this.hasAttribute("autoplay"), this._controls = this.hasAttribute("controls"), this._loop = this.hasAttribute("loop"), this._muted = this.hasAttribute("muted"), this._playsinline = this.hasAttribute("playsinline"), this._preload = this.getAttribute("preload") || "auto", this._poster = this.getAttribute("poster") || "";
|
|
115942
115938
|
const v = this.getAttribute("volume");
|
|
@@ -116383,7 +116379,11 @@ class MoviElement extends HTMLElement {
|
|
|
116383
116379
|
};
|
|
116384
116380
|
this.player.trackManager.on("tracksChange", b), this.eventHandlers.set("tracksChange", () => this.player?.trackManager.off("tracksChange", b));
|
|
116385
116381
|
const j = (A2) => {
|
|
116386
|
-
if (Logger$1.info(TAG, `stateChange: ${A2}`),
|
|
116382
|
+
if (Logger$1.info(TAG, `stateChange: ${A2}`), null !== this._pendingSeek && ("ready" === A2 || "paused" === A2 || "playing" === A2)) {
|
|
116383
|
+
const A3 = this._pendingSeek;
|
|
116384
|
+
this._pendingSeek = null, this.currentTime = A3;
|
|
116385
|
+
}
|
|
116386
|
+
if ("playing" === A2 && this.posterElement && (this._qualitySwitchInProgress && (this._hideSnapshotPoster(), this._qualitySwitchInProgress = false, this._switchResumeTime = 0, this._switchResumeDuration = 0), this.posterElement.style.display = "none"), this.dispatchEvent(new CustomEvent("statechange", { detail: A2 })), this.updateLoadingIndicator(A2), this.updateControlsState(), this.updatePlayPauseIcon(), !this._autoplayStarting || "paused" !== A2 && "ended" !== A2 && "error" !== A2 || (this._autoplayStarting = false, this.updatePlayPauseIcon()), "playing" === A2) {
|
|
116387
116387
|
const A3 = this._autoplayStarting;
|
|
116388
116388
|
if (this._autoplayStarting = false, this._resumeDialogPending && !this._hasEverPlayed && (this._resumeDialogPending = false, this.maybeShowResumeDialog()), this._hasEverPlayed = true, this._loopRestartInFlight = false, this.dispatchEvent(new Event("play")), A3) return this.hideControls(), this.updatePlayPauseIcon(), this._ambientMode && (this._ambientSampleInterval = 200), void ("mediaSession" in navigator && this._title && (navigator.mediaSession.metadata = new MediaMetadata({ title: this._title })));
|
|
116389
116389
|
window.setTimeout(() => {
|
|
@@ -117161,10 +117161,11 @@ class MoviElement extends HTMLElement {
|
|
|
117161
117161
|
return this.player?.getCurrentTime() || 0;
|
|
117162
117162
|
}
|
|
117163
117163
|
set currentTime(A) {
|
|
117164
|
-
if (!this.player) return;
|
|
117164
|
+
if (!this.player) return void (this._pendingSeek = A);
|
|
117165
117165
|
A = this.clampToBufferedWindow(A);
|
|
117166
117166
|
const v = this.player.getState();
|
|
117167
|
-
Logger$1.info(TAG, `currentTime setter: value=${A.toFixed(2)}, state=${v}, isSeeking=${this.isSeeking}`), "ready"
|
|
117167
|
+
if (Logger$1.info(TAG, `currentTime setter: value=${A.toFixed(2)}, state=${v}, isSeeking=${this.isSeeking}`), "ready" !== v && "playing" !== v && "paused" !== v && "ended" !== v && "seeking" !== v && "buffering" !== v) return Logger$1.info(TAG, `Seek held until ready — state=${v}`), void (this._pendingSeek = A);
|
|
117168
|
+
this._pendingSeek = null, this.isSeeking ? this.pendingSeekTarget = A : (this.isSeeking = true, this.player.seek(A).then(() => {
|
|
117168
117169
|
Logger$1.info(TAG, `Seek resolved: value=${A.toFixed(2)}, newState=${this.player?.getState()}`);
|
|
117169
117170
|
}).catch((v2) => {
|
|
117170
117171
|
Logger$1.error(TAG, `Seek error: value=${A.toFixed(2)}`, v2);
|
|
@@ -117173,7 +117174,7 @@ class MoviElement extends HTMLElement {
|
|
|
117173
117174
|
const A2 = this.pendingSeekTarget;
|
|
117174
117175
|
this.pendingSeekTarget = null, this.currentTime = A2;
|
|
117175
117176
|
}
|
|
117176
|
-
}))
|
|
117177
|
+
}));
|
|
117177
117178
|
}
|
|
117178
117179
|
get renderer() {
|
|
117179
117180
|
return this._renderer;
|
package/dist/element.js
CHANGED
|
@@ -49965,7 +49965,7 @@ class MoviVideoDecoder {
|
|
|
49965
49965
|
}
|
|
49966
49966
|
async configure(A2, t2, n2 = 0) {
|
|
49967
49967
|
if (this.currentTrack = A2, this.targetFps = n2, this.currentProfile = A2.profile, this.useSoftware = false, this.requiresSoftware = false, this.isAnnexBSource = false, this.openGopErrorCount = 0, this.hardwareRetryCount = 0, this.lastHardwareRetryTime = 0, this.swDecoder && (this.swDecoder.close(), this.swDecoder = null), this.forceSoftware) return v.info(K, "Force software decoding enabled, using WASM decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49968
|
-
if (!("VideoDecoder" in window)) return v.
|
|
49968
|
+
if (!("VideoDecoder" in window)) return v.warn(K, "WebCodecs VideoDecoder not supported — falling back to software decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49969
49969
|
let b2 = CodecParser.getCodecString(A2.codec, A2.extradata);
|
|
49970
49970
|
if (b2 || (v.debug(K, "CodecParser returned null, falling back to manual mapping"), b2 = this.mapCodecToWebCodecs(A2.codec, A2.width, A2.height, A2.profile, A2.level)), !b2) return v.error(K, `Unsupported codec: ${A2.codec}`), false;
|
|
49971
49971
|
const j2 = { codec: b2, codedWidth: A2.width, codedHeight: A2.height, hardwareAcceleration: "prefer-hardware" };
|
|
@@ -108990,6 +108990,7 @@ class MoviElement extends HTMLElement {
|
|
|
108990
108990
|
isOverControls = false;
|
|
108991
108991
|
isSeeking = false;
|
|
108992
108992
|
pendingSeekTarget = null;
|
|
108993
|
+
_pendingSeek = null;
|
|
108993
108994
|
isDragging = false;
|
|
108994
108995
|
isTouchDragging = false;
|
|
108995
108996
|
touchStartX = 0;
|
|
@@ -109115,7 +109116,7 @@ class MoviElement extends HTMLElement {
|
|
|
109115
109116
|
return ["src", "autoplay", "controls", "loop", "muted", "playsinline", "preload", "poster", "width", "height", "crossorigin", "volume", "playbackrate", "subtitledelay", "subtitlesize", "subtitlecolor", "subtitlebg", "subtitleedge", "ambientmode", "ambientwrapper", "renderer", "objectfit", "thumb", "hdr", "theme", "sw", "fps", "gesturefs", "nohotkeys", "startat", "fastseek", "doubletap", "themecolor", "buffersize", "title", "showtitle", "resume", "stablevolume", "encrypted", "tokenurl", "videourl", "videoid", "drm", "licenseurl", "licenseheaders", "headers", "audioonly", "lcevc", "lcevcurl", "postertime"];
|
|
109116
109117
|
}
|
|
109117
109118
|
constructor() {
|
|
109118
|
-
super(),
|
|
109119
|
+
super(), v.setLevel(A.DEBUG);
|
|
109119
109120
|
const t2 = this.attachShadow({ mode: "open" });
|
|
109120
109121
|
this.canvas = document.createElement("canvas"), this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.display = "block", this.canvas.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), t2.appendChild(this.canvas), this.video = document.createElement("video"), this.video.style.width = "100%", this.video.style.height = "100%", this.video.style.display = "none", this.video.style.objectFit = "contain", this.video.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), t2.appendChild(this.video), this.posterElement = document.createElement("img"), this.posterElement.className = "movi-poster-overlay", this.posterElement.crossOrigin = "anonymous", this.posterElement.referrerPolicy = "no-referrer", this.posterElement.decoding = "async", this.posterElement.addEventListener("error", () => {
|
|
109121
109122
|
const A2 = this.posterElement.src.match(/\/vi\/([\w-]+)\/maxresdefault\.jpg/);
|
|
@@ -110982,6 +110983,7 @@ class MoviElement extends HTMLElement {
|
|
|
110982
110983
|
const A3 = this.player?.getState();
|
|
110983
110984
|
"playing" !== A3 && "buffering" !== A3 && v2.classList.add("movi-center-visible");
|
|
110984
110985
|
}
|
|
110986
|
+
this._hasEverPlayed ? this.classList.add("movi-bar-visible") : this.classList.remove("movi-bar-visible");
|
|
110985
110987
|
const j2 = this.shadowRoot?.querySelector(".movi-controls-bar"), s2 = j2?.offsetHeight ?? 80, f2 = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
110986
110988
|
let l2 = s2 + 20;
|
|
110987
110989
|
if (f2 && "none" !== f2.style.display ? (f2.style.bottom = `${s2 + 20}px`, requestAnimationFrame(() => {
|
|
@@ -111071,7 +111073,7 @@ class MoviElement extends HTMLElement {
|
|
|
111071
111073
|
v3 && (v3.style.cursor = "none");
|
|
111072
111074
|
}
|
|
111073
111075
|
const t2 = this.shadowRoot?.querySelector(".movi-center-play-pause"), v2 = this.player?.getState();
|
|
111074
|
-
t2 && "playing" === v2 && t2.classList.remove("movi-center-visible");
|
|
111076
|
+
t2 && "playing" === v2 && t2.classList.remove("movi-center-visible"), this.classList.remove("movi-bar-visible");
|
|
111075
111077
|
const n2 = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
111076
111078
|
if (n2 && (n2.style.bottom = "12px"), this.player && (n2 && "none" !== n2.style.display ? requestAnimationFrame(() => {
|
|
111077
111079
|
const A3 = n2.offsetHeight || 0;
|
|
@@ -111253,6 +111255,14 @@ class MoviElement extends HTMLElement {
|
|
|
111253
111255
|
-moz-osx-font-smoothing: grayscale;
|
|
111254
111256
|
}
|
|
111255
111257
|
|
|
111258
|
+
/* The :host{display:block} above is an author rule, so it beats the
|
|
111259
|
+
UA stylesheet's [hidden]{display:none}. Without this, the standard
|
|
111260
|
+
hidden attribute does nothing and the player stays visible. Honour
|
|
111261
|
+
it explicitly. !important so source-order/specificity can't regress it. */
|
|
111262
|
+
:host([hidden]) {
|
|
111263
|
+
display: none !important;
|
|
111264
|
+
}
|
|
111265
|
+
|
|
111256
111266
|
/* Light Theme Override */
|
|
111257
111267
|
:host([theme="light"]) {
|
|
111258
111268
|
--movi-primary: #7c3aed; /* Vibrancy boost for light theme */
|
|
@@ -113841,12 +113851,13 @@ class MoviElement extends HTMLElement {
|
|
|
113841
113851
|
height: 64px !important;
|
|
113842
113852
|
}
|
|
113843
113853
|
|
|
113844
|
-
/*
|
|
113854
|
+
/* Keyframe animations off on small/compact layouts for perf, but keep
|
|
113855
|
+
CSS transitions so the controls + centre button still move smoothly
|
|
113856
|
+
here too (the PiP / mini player is a small container). */
|
|
113845
113857
|
.movi-controls-overlay,
|
|
113846
113858
|
.movi-center-play-pause,
|
|
113847
113859
|
.movi-btn,
|
|
113848
113860
|
.movi-progress-handle {
|
|
113849
|
-
transition: none !important;
|
|
113850
113861
|
animation: none !important;
|
|
113851
113862
|
transform: none !important;
|
|
113852
113863
|
}
|
|
@@ -114338,7 +114349,7 @@ class MoviElement extends HTMLElement {
|
|
|
114338
114349
|
button's bar-hidden and both-bars-visible rules exactly. */
|
|
114339
114350
|
.movi-loading-indicator {
|
|
114340
114351
|
position: absolute;
|
|
114341
|
-
top:
|
|
114352
|
+
top: 50%;
|
|
114342
114353
|
left: 50%;
|
|
114343
114354
|
transform: translate(-50%, -50%);
|
|
114344
114355
|
display: flex;
|
|
@@ -114347,15 +114358,7 @@ class MoviElement extends HTMLElement {
|
|
|
114347
114358
|
z-index: 1000;
|
|
114348
114359
|
pointer-events: none;
|
|
114349
114360
|
background: transparent;
|
|
114350
|
-
|
|
114351
|
-
|
|
114352
|
-
:host:has(.movi-controls-container.movi-controls-hidden) .movi-loading-indicator,
|
|
114353
|
-
:host(:not([controls])) .movi-loading-indicator {
|
|
114354
|
-
top: 50%;
|
|
114355
|
-
}
|
|
114356
|
-
|
|
114357
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-loading-indicator {
|
|
114358
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114361
|
+
transition: top var(--movi-transition-normal);
|
|
114359
114362
|
}
|
|
114360
114363
|
|
|
114361
114364
|
.movi-loader-container {
|
|
@@ -114397,7 +114400,7 @@ class MoviElement extends HTMLElement {
|
|
|
114397
114400
|
down adjust this for the other two layout states. */
|
|
114398
114401
|
.movi-center-play-pause {
|
|
114399
114402
|
position: absolute;
|
|
114400
|
-
top:
|
|
114403
|
+
top: 50%;
|
|
114401
114404
|
left: 50%;
|
|
114402
114405
|
transform: translate(-50%, -50%) scale(0.8);
|
|
114403
114406
|
z-index: 5;
|
|
@@ -114426,23 +114429,15 @@ class MoviElement extends HTMLElement {
|
|
|
114426
114429
|
transition-delay: 0s;
|
|
114427
114430
|
}
|
|
114428
114431
|
|
|
114429
|
-
/*
|
|
114430
|
-
|
|
114431
|
-
|
|
114432
|
-
|
|
114433
|
-
|
|
114434
|
-
|
|
114435
|
-
|
|
114436
|
-
|
|
114437
|
-
|
|
114438
|
-
top), not the full player. The 44% default biases too far up
|
|
114439
|
-
when there's also a title bar to balance the controls; here
|
|
114440
|
-
the offset is just half the *difference* between the two
|
|
114441
|
-
chrome heights (title ≈ 52px, controls 72px → ~10px above
|
|
114442
|
-
centre on desktop). calc() keeps it right on mobile where
|
|
114443
|
-
--movi-controls-height drops to 64px too. */
|
|
114444
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-center-play-pause {
|
|
114445
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114432
|
+
/* Default (the base rule) is the true geometric centre. When the controls
|
|
114433
|
+
bar is visible, lift the centre button AND the loading spinner a little
|
|
114434
|
+
so they read as centred in the band above the bar. Keyed off a host
|
|
114435
|
+
class toggled in show/hideControls, because :host:has() checks against
|
|
114436
|
+
the shadow tree don't apply in every engine (notably Electron). The
|
|
114437
|
+
transition on top (in each base rule) animates the move. */
|
|
114438
|
+
:host(.movi-bar-visible) .movi-center-play-pause,
|
|
114439
|
+
:host(.movi-bar-visible) .movi-loading-indicator {
|
|
114440
|
+
top: calc(50% - var(--movi-controls-height) / 4);
|
|
114446
114441
|
}
|
|
114447
114442
|
|
|
114448
114443
|
.movi-center-play-pause:hover {
|
|
@@ -116041,6 +116036,7 @@ class MoviElement extends HTMLElement {
|
|
|
116041
116036
|
});
|
|
116042
116037
|
};
|
|
116043
116038
|
connectedCallback() {
|
|
116039
|
+
this.hasAttribute("tabindex") || (this.tabIndex = 0);
|
|
116044
116040
|
const A2 = this.getAttribute("src");
|
|
116045
116041
|
this._src = A2 || null, this._autoplay = this.hasAttribute("autoplay"), this._controls = this.hasAttribute("controls"), this._loop = this.hasAttribute("loop"), this._muted = this.hasAttribute("muted"), this._playsinline = this.hasAttribute("playsinline"), this._preload = this.getAttribute("preload") || "auto", this._poster = this.getAttribute("poster") || "";
|
|
116046
116042
|
const t2 = this.getAttribute("volume");
|
|
@@ -116487,7 +116483,11 @@ class MoviElement extends HTMLElement {
|
|
|
116487
116483
|
};
|
|
116488
116484
|
this.player.trackManager.on("tracksChange", n2), this.eventHandlers.set("tracksChange", () => this.player?.trackManager.off("tracksChange", n2));
|
|
116489
116485
|
const b2 = (A3) => {
|
|
116490
|
-
if (v.info(jj, `stateChange: ${A3}`),
|
|
116486
|
+
if (v.info(jj, `stateChange: ${A3}`), null !== this._pendingSeek && ("ready" === A3 || "paused" === A3 || "playing" === A3)) {
|
|
116487
|
+
const A4 = this._pendingSeek;
|
|
116488
|
+
this._pendingSeek = null, this.currentTime = A4;
|
|
116489
|
+
}
|
|
116490
|
+
if ("playing" === A3 && this.posterElement && (this._qualitySwitchInProgress && (this._hideSnapshotPoster(), this._qualitySwitchInProgress = false, this._switchResumeTime = 0, this._switchResumeDuration = 0), this.posterElement.style.display = "none"), this.dispatchEvent(new CustomEvent("statechange", { detail: A3 })), this.updateLoadingIndicator(A3), this.updateControlsState(), this.updatePlayPauseIcon(), !this._autoplayStarting || "paused" !== A3 && "ended" !== A3 && "error" !== A3 || (this._autoplayStarting = false, this.updatePlayPauseIcon()), "playing" === A3) {
|
|
116491
116491
|
const A4 = this._autoplayStarting;
|
|
116492
116492
|
if (this._autoplayStarting = false, this._resumeDialogPending && !this._hasEverPlayed && (this._resumeDialogPending = false, this.maybeShowResumeDialog()), this._hasEverPlayed = true, this._loopRestartInFlight = false, this.dispatchEvent(new Event("play")), A4) return this.hideControls(), this.updatePlayPauseIcon(), this._ambientMode && (this._ambientSampleInterval = 200), void ("mediaSession" in navigator && this._title && (navigator.mediaSession.metadata = new MediaMetadata({ title: this._title })));
|
|
116493
116493
|
window.setTimeout(() => {
|
|
@@ -117265,10 +117265,11 @@ class MoviElement extends HTMLElement {
|
|
|
117265
117265
|
return this.player?.getCurrentTime() || 0;
|
|
117266
117266
|
}
|
|
117267
117267
|
set currentTime(A2) {
|
|
117268
|
-
if (!this.player) return;
|
|
117268
|
+
if (!this.player) return void (this._pendingSeek = A2);
|
|
117269
117269
|
A2 = this.clampToBufferedWindow(A2);
|
|
117270
117270
|
const t2 = this.player.getState();
|
|
117271
|
-
v.info(jj, `currentTime setter: value=${A2.toFixed(2)}, state=${t2}, isSeeking=${this.isSeeking}`), "ready"
|
|
117271
|
+
if (v.info(jj, `currentTime setter: value=${A2.toFixed(2)}, state=${t2}, isSeeking=${this.isSeeking}`), "ready" !== t2 && "playing" !== t2 && "paused" !== t2 && "ended" !== t2 && "seeking" !== t2 && "buffering" !== t2) return v.info(jj, `Seek held until ready — state=${t2}`), void (this._pendingSeek = A2);
|
|
117272
|
+
this._pendingSeek = null, this.isSeeking ? this.pendingSeekTarget = A2 : (this.isSeeking = true, this.player.seek(A2).then(() => {
|
|
117272
117273
|
v.info(jj, `Seek resolved: value=${A2.toFixed(2)}, newState=${this.player?.getState()}`);
|
|
117273
117274
|
}).catch((t3) => {
|
|
117274
117275
|
v.error(jj, `Seek error: value=${A2.toFixed(2)}`, t3);
|
|
@@ -117277,7 +117278,7 @@ class MoviElement extends HTMLElement {
|
|
|
117277
117278
|
const A3 = this.pendingSeekTarget;
|
|
117278
117279
|
this.pendingSeekTarget = null, this.currentTime = A3;
|
|
117279
117280
|
}
|
|
117280
|
-
}))
|
|
117281
|
+
}));
|
|
117281
117282
|
}
|
|
117282
117283
|
get renderer() {
|
|
117283
117284
|
return this._renderer;
|
package/dist/index.cjs
CHANGED
|
@@ -49950,7 +49950,7 @@ class MoviVideoDecoder {
|
|
|
49950
49950
|
}
|
|
49951
49951
|
async configure(A, v, b = 0) {
|
|
49952
49952
|
if (this.currentTrack = A, this.targetFps = b, this.currentProfile = A.profile, this.useSoftware = false, this.requiresSoftware = false, this.isAnnexBSource = false, this.openGopErrorCount = 0, this.hardwareRetryCount = 0, this.lastHardwareRetryTime = 0, this.swDecoder && (this.swDecoder.close(), this.swDecoder = null), this.forceSoftware) return Logger$1.info(TAG$h, "Force software decoding enabled, using WASM decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49953
|
-
if (!("VideoDecoder" in window)) return Logger$1.
|
|
49953
|
+
if (!("VideoDecoder" in window)) return Logger$1.warn(TAG$h, "WebCodecs VideoDecoder not supported — falling back to software decoder"), this.useSoftware = true, this.initSoftwareDecoder();
|
|
49954
49954
|
let j = CodecParser.getCodecString(A.codec, A.extradata);
|
|
49955
49955
|
if (j || (Logger$1.debug(TAG$h, "CodecParser returned null, falling back to manual mapping"), j = this.mapCodecToWebCodecs(A.codec, A.width, A.height, A.profile, A.level)), !j) return Logger$1.error(TAG$h, `Unsupported codec: ${A.codec}`), false;
|
|
49956
49956
|
const s2 = { codec: j, codedWidth: A.width, codedHeight: A.height, hardwareAcceleration: "prefer-hardware" };
|
|
@@ -108886,6 +108886,7 @@ class MoviElement extends HTMLElement {
|
|
|
108886
108886
|
isOverControls = false;
|
|
108887
108887
|
isSeeking = false;
|
|
108888
108888
|
pendingSeekTarget = null;
|
|
108889
|
+
_pendingSeek = null;
|
|
108889
108890
|
isDragging = false;
|
|
108890
108891
|
isTouchDragging = false;
|
|
108891
108892
|
touchStartX = 0;
|
|
@@ -109011,7 +109012,7 @@ class MoviElement extends HTMLElement {
|
|
|
109011
109012
|
return ["src", "autoplay", "controls", "loop", "muted", "playsinline", "preload", "poster", "width", "height", "crossorigin", "volume", "playbackrate", "subtitledelay", "subtitlesize", "subtitlecolor", "subtitlebg", "subtitleedge", "ambientmode", "ambientwrapper", "renderer", "objectfit", "thumb", "hdr", "theme", "sw", "fps", "gesturefs", "nohotkeys", "startat", "fastseek", "doubletap", "themecolor", "buffersize", "title", "showtitle", "resume", "stablevolume", "encrypted", "tokenurl", "videourl", "videoid", "drm", "licenseurl", "licenseheaders", "headers", "audioonly", "lcevc", "lcevcurl", "postertime"];
|
|
109012
109013
|
}
|
|
109013
109014
|
constructor() {
|
|
109014
|
-
super(),
|
|
109015
|
+
super(), Logger$1.setLevel(LogLevel.DEBUG);
|
|
109015
109016
|
const A = this.attachShadow({ mode: "open" });
|
|
109016
109017
|
this.canvas = document.createElement("canvas"), this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.display = "block", this.canvas.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), A.appendChild(this.canvas), this.video = document.createElement("video"), this.video.style.width = "100%", this.video.style.height = "100%", this.video.style.display = "none", this.video.style.objectFit = "contain", this.video.oncontextmenu = (A2) => (A2.preventDefault(), A2.stopPropagation(), false), A.appendChild(this.video), this.posterElement = document.createElement("img"), this.posterElement.className = "movi-poster-overlay", this.posterElement.crossOrigin = "anonymous", this.posterElement.referrerPolicy = "no-referrer", this.posterElement.decoding = "async", this.posterElement.addEventListener("error", () => {
|
|
109017
109018
|
const A2 = this.posterElement.src.match(/\/vi\/([\w-]+)\/maxresdefault\.jpg/);
|
|
@@ -110878,6 +110879,7 @@ class MoviElement extends HTMLElement {
|
|
|
110878
110879
|
const A2 = this.player?.getState();
|
|
110879
110880
|
"playing" !== A2 && "buffering" !== A2 && b.classList.add("movi-center-visible");
|
|
110880
110881
|
}
|
|
110882
|
+
this._hasEverPlayed ? this.classList.add("movi-bar-visible") : this.classList.remove("movi-bar-visible");
|
|
110881
110883
|
const E = this.shadowRoot?.querySelector(".movi-controls-bar"), F = E?.offsetHeight ?? 80, k = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
110882
110884
|
let x = F + 20;
|
|
110883
110885
|
if (k && "none" !== k.style.display ? (k.style.bottom = `${F + 20}px`, requestAnimationFrame(() => {
|
|
@@ -110967,7 +110969,7 @@ class MoviElement extends HTMLElement {
|
|
|
110967
110969
|
b2 && (b2.style.cursor = "none");
|
|
110968
110970
|
}
|
|
110969
110971
|
const v = this.shadowRoot?.querySelector(".movi-center-play-pause"), b = this.player?.getState();
|
|
110970
|
-
v && "playing" === b && v.classList.remove("movi-center-visible");
|
|
110972
|
+
v && "playing" === b && v.classList.remove("movi-center-visible"), this.classList.remove("movi-bar-visible");
|
|
110971
110973
|
const j = this.shadowRoot?.querySelector(".movi-timeline-panel");
|
|
110972
110974
|
if (j && (j.style.bottom = "12px"), this.player && (j && "none" !== j.style.display ? requestAnimationFrame(() => {
|
|
110973
110975
|
const A2 = j.offsetHeight || 0;
|
|
@@ -111149,6 +111151,14 @@ class MoviElement extends HTMLElement {
|
|
|
111149
111151
|
-moz-osx-font-smoothing: grayscale;
|
|
111150
111152
|
}
|
|
111151
111153
|
|
|
111154
|
+
/* The :host{display:block} above is an author rule, so it beats the
|
|
111155
|
+
UA stylesheet's [hidden]{display:none}. Without this, the standard
|
|
111156
|
+
hidden attribute does nothing and the player stays visible. Honour
|
|
111157
|
+
it explicitly. !important so source-order/specificity can't regress it. */
|
|
111158
|
+
:host([hidden]) {
|
|
111159
|
+
display: none !important;
|
|
111160
|
+
}
|
|
111161
|
+
|
|
111152
111162
|
/* Light Theme Override */
|
|
111153
111163
|
:host([theme="light"]) {
|
|
111154
111164
|
--movi-primary: #7c3aed; /* Vibrancy boost for light theme */
|
|
@@ -113737,12 +113747,13 @@ class MoviElement extends HTMLElement {
|
|
|
113737
113747
|
height: 64px !important;
|
|
113738
113748
|
}
|
|
113739
113749
|
|
|
113740
|
-
/*
|
|
113750
|
+
/* Keyframe animations off on small/compact layouts for perf, but keep
|
|
113751
|
+
CSS transitions so the controls + centre button still move smoothly
|
|
113752
|
+
here too (the PiP / mini player is a small container). */
|
|
113741
113753
|
.movi-controls-overlay,
|
|
113742
113754
|
.movi-center-play-pause,
|
|
113743
113755
|
.movi-btn,
|
|
113744
113756
|
.movi-progress-handle {
|
|
113745
|
-
transition: none !important;
|
|
113746
113757
|
animation: none !important;
|
|
113747
113758
|
transform: none !important;
|
|
113748
113759
|
}
|
|
@@ -114234,7 +114245,7 @@ class MoviElement extends HTMLElement {
|
|
|
114234
114245
|
button's bar-hidden and both-bars-visible rules exactly. */
|
|
114235
114246
|
.movi-loading-indicator {
|
|
114236
114247
|
position: absolute;
|
|
114237
|
-
top:
|
|
114248
|
+
top: 50%;
|
|
114238
114249
|
left: 50%;
|
|
114239
114250
|
transform: translate(-50%, -50%);
|
|
114240
114251
|
display: flex;
|
|
@@ -114243,15 +114254,7 @@ class MoviElement extends HTMLElement {
|
|
|
114243
114254
|
z-index: 1000;
|
|
114244
114255
|
pointer-events: none;
|
|
114245
114256
|
background: transparent;
|
|
114246
|
-
|
|
114247
|
-
|
|
114248
|
-
:host:has(.movi-controls-container.movi-controls-hidden) .movi-loading-indicator,
|
|
114249
|
-
:host(:not([controls])) .movi-loading-indicator {
|
|
114250
|
-
top: 50%;
|
|
114251
|
-
}
|
|
114252
|
-
|
|
114253
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-loading-indicator {
|
|
114254
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114257
|
+
transition: top var(--movi-transition-normal);
|
|
114255
114258
|
}
|
|
114256
114259
|
|
|
114257
114260
|
.movi-loader-container {
|
|
@@ -114293,7 +114296,7 @@ class MoviElement extends HTMLElement {
|
|
|
114293
114296
|
down adjust this for the other two layout states. */
|
|
114294
114297
|
.movi-center-play-pause {
|
|
114295
114298
|
position: absolute;
|
|
114296
|
-
top:
|
|
114299
|
+
top: 50%;
|
|
114297
114300
|
left: 50%;
|
|
114298
114301
|
transform: translate(-50%, -50%) scale(0.8);
|
|
114299
114302
|
z-index: 5;
|
|
@@ -114322,23 +114325,15 @@ class MoviElement extends HTMLElement {
|
|
|
114322
114325
|
transition-delay: 0s;
|
|
114323
114326
|
}
|
|
114324
114327
|
|
|
114325
|
-
/*
|
|
114326
|
-
|
|
114327
|
-
|
|
114328
|
-
|
|
114329
|
-
|
|
114330
|
-
|
|
114331
|
-
|
|
114332
|
-
|
|
114333
|
-
|
|
114334
|
-
top), not the full player. The 44% default biases too far up
|
|
114335
|
-
when there's also a title bar to balance the controls; here
|
|
114336
|
-
the offset is just half the *difference* between the two
|
|
114337
|
-
chrome heights (title ≈ 52px, controls 72px → ~10px above
|
|
114338
|
-
centre on desktop). calc() keeps it right on mobile where
|
|
114339
|
-
--movi-controls-height drops to 64px too. */
|
|
114340
|
-
:host:has(.movi-controls-container.movi-controls-visible):has(.movi-title-bar.movi-title-visible) .movi-center-play-pause {
|
|
114341
|
-
top: calc(50% - (var(--movi-controls-height) - 52px) / 2);
|
|
114328
|
+
/* Default (the base rule) is the true geometric centre. When the controls
|
|
114329
|
+
bar is visible, lift the centre button AND the loading spinner a little
|
|
114330
|
+
so they read as centred in the band above the bar. Keyed off a host
|
|
114331
|
+
class toggled in show/hideControls, because :host:has() checks against
|
|
114332
|
+
the shadow tree don't apply in every engine (notably Electron). The
|
|
114333
|
+
transition on top (in each base rule) animates the move. */
|
|
114334
|
+
:host(.movi-bar-visible) .movi-center-play-pause,
|
|
114335
|
+
:host(.movi-bar-visible) .movi-loading-indicator {
|
|
114336
|
+
top: calc(50% - var(--movi-controls-height) / 4);
|
|
114342
114337
|
}
|
|
114343
114338
|
|
|
114344
114339
|
.movi-center-play-pause:hover {
|
|
@@ -115937,6 +115932,7 @@ class MoviElement extends HTMLElement {
|
|
|
115937
115932
|
});
|
|
115938
115933
|
};
|
|
115939
115934
|
connectedCallback() {
|
|
115935
|
+
this.hasAttribute("tabindex") || (this.tabIndex = 0);
|
|
115940
115936
|
const A = this.getAttribute("src");
|
|
115941
115937
|
this._src = A || null, this._autoplay = this.hasAttribute("autoplay"), this._controls = this.hasAttribute("controls"), this._loop = this.hasAttribute("loop"), this._muted = this.hasAttribute("muted"), this._playsinline = this.hasAttribute("playsinline"), this._preload = this.getAttribute("preload") || "auto", this._poster = this.getAttribute("poster") || "";
|
|
115942
115938
|
const v = this.getAttribute("volume");
|
|
@@ -116383,7 +116379,11 @@ class MoviElement extends HTMLElement {
|
|
|
116383
116379
|
};
|
|
116384
116380
|
this.player.trackManager.on("tracksChange", b), this.eventHandlers.set("tracksChange", () => this.player?.trackManager.off("tracksChange", b));
|
|
116385
116381
|
const j = (A2) => {
|
|
116386
|
-
if (Logger$1.info(TAG, `stateChange: ${A2}`),
|
|
116382
|
+
if (Logger$1.info(TAG, `stateChange: ${A2}`), null !== this._pendingSeek && ("ready" === A2 || "paused" === A2 || "playing" === A2)) {
|
|
116383
|
+
const A3 = this._pendingSeek;
|
|
116384
|
+
this._pendingSeek = null, this.currentTime = A3;
|
|
116385
|
+
}
|
|
116386
|
+
if ("playing" === A2 && this.posterElement && (this._qualitySwitchInProgress && (this._hideSnapshotPoster(), this._qualitySwitchInProgress = false, this._switchResumeTime = 0, this._switchResumeDuration = 0), this.posterElement.style.display = "none"), this.dispatchEvent(new CustomEvent("statechange", { detail: A2 })), this.updateLoadingIndicator(A2), this.updateControlsState(), this.updatePlayPauseIcon(), !this._autoplayStarting || "paused" !== A2 && "ended" !== A2 && "error" !== A2 || (this._autoplayStarting = false, this.updatePlayPauseIcon()), "playing" === A2) {
|
|
116387
116387
|
const A3 = this._autoplayStarting;
|
|
116388
116388
|
if (this._autoplayStarting = false, this._resumeDialogPending && !this._hasEverPlayed && (this._resumeDialogPending = false, this.maybeShowResumeDialog()), this._hasEverPlayed = true, this._loopRestartInFlight = false, this.dispatchEvent(new Event("play")), A3) return this.hideControls(), this.updatePlayPauseIcon(), this._ambientMode && (this._ambientSampleInterval = 200), void ("mediaSession" in navigator && this._title && (navigator.mediaSession.metadata = new MediaMetadata({ title: this._title })));
|
|
116389
116389
|
window.setTimeout(() => {
|
|
@@ -117161,10 +117161,11 @@ class MoviElement extends HTMLElement {
|
|
|
117161
117161
|
return this.player?.getCurrentTime() || 0;
|
|
117162
117162
|
}
|
|
117163
117163
|
set currentTime(A) {
|
|
117164
|
-
if (!this.player) return;
|
|
117164
|
+
if (!this.player) return void (this._pendingSeek = A);
|
|
117165
117165
|
A = this.clampToBufferedWindow(A);
|
|
117166
117166
|
const v = this.player.getState();
|
|
117167
|
-
Logger$1.info(TAG, `currentTime setter: value=${A.toFixed(2)}, state=${v}, isSeeking=${this.isSeeking}`), "ready"
|
|
117167
|
+
if (Logger$1.info(TAG, `currentTime setter: value=${A.toFixed(2)}, state=${v}, isSeeking=${this.isSeeking}`), "ready" !== v && "playing" !== v && "paused" !== v && "ended" !== v && "seeking" !== v && "buffering" !== v) return Logger$1.info(TAG, `Seek held until ready — state=${v}`), void (this._pendingSeek = A);
|
|
117168
|
+
this._pendingSeek = null, this.isSeeking ? this.pendingSeekTarget = A : (this.isSeeking = true, this.player.seek(A).then(() => {
|
|
117168
117169
|
Logger$1.info(TAG, `Seek resolved: value=${A.toFixed(2)}, newState=${this.player?.getState()}`);
|
|
117169
117170
|
}).catch((v2) => {
|
|
117170
117171
|
Logger$1.error(TAG, `Seek error: value=${A.toFixed(2)}`, v2);
|
|
@@ -117173,7 +117174,7 @@ class MoviElement extends HTMLElement {
|
|
|
117173
117174
|
const A2 = this.pendingSeekTarget;
|
|
117174
117175
|
this.pendingSeekTarget = null, this.currentTime = A2;
|
|
117175
117176
|
}
|
|
117176
|
-
}))
|
|
117177
|
+
}));
|
|
117177
117178
|
}
|
|
117178
117179
|
get renderer() {
|
|
117179
117180
|
return this._renderer;
|