movi-player 0.3.4 → 0.3.5

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/element.js CHANGED
@@ -51313,10 +51313,10 @@ class CanvasRenderer {
51313
51313
  v.error(Y, "Error redrawing frame after resize", A3);
51314
51314
  }
51315
51315
  if (this.subtitleOverlay) {
51316
- const v2 = A2, n3 = t2, b3 = CanvasRenderer.computeSubtitleBottomPadding(n3);
51317
- this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.top = "0", this.subtitleOverlay.style.left = "0", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${v2}px`, this.subtitleOverlay.style.height = `${n3}px`, this.subtitleOverlay.style.margin = "0", this.subtitleOverlay.style.padding = "0";
51318
- const j3 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : b3;
51319
- this.subtitleOverlay.style.paddingBottom = `${j3}px`, this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.transform = "none", this.subtitleOverlay.style.boxSizing = "border-box", this.activeSubtitleCue && u2 && this.scheduleSubtitleRerender();
51316
+ const v2 = ((this.rotation ?? 0) % 360 + 360) % 360, n3 = 90 === v2 || 270 === v2, b3 = n3 ? t2 : A2, j3 = n3 ? A2 : t2, s3 = CanvasRenderer.computeSubtitleBottomPadding(j3);
51317
+ this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${b3}px`, this.subtitleOverlay.style.height = `${j3}px`, this.subtitleOverlay.style.left = (A2 - b3) / 2 + "px", this.subtitleOverlay.style.top = (t2 - j3) / 2 + "px", this.subtitleOverlay.style.margin = "0", this.subtitleOverlay.style.padding = "0";
51318
+ const f3 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : s3;
51319
+ this.subtitleOverlay.style.paddingBottom = `${f3}px`, this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.transformOrigin = "center center", this.subtitleOverlay.style.transform = v2 ? `rotate(${v2}deg)` : "none", this.subtitleOverlay.style.boxSizing = "border-box", this.activeSubtitleCue && u2 && this.scheduleSubtitleRerender();
51320
51320
  }
51321
51321
  }
51322
51322
  }
@@ -51620,15 +51620,17 @@ class CanvasRenderer {
51620
51620
  const A3 = l2 - g2 - _2;
51621
51621
  B2 = A3 < 0 ? Math.max(0, l2 - g2 - 10) : A3, B2 = Math.max(0, Math.min(B2, l2 - g2));
51622
51622
  }
51623
- T2 = Math.max(0, Math.min(T2, f2 - k2)), this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.top = "0", this.subtitleOverlay.style.left = "0", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${f2}px`, this.subtitleOverlay.style.height = `${l2}px`, this.subtitleOverlay.style.pointerEvents = "none", this.subtitleOverlay.style.transform = "none", this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.overflow = "hidden", this.subtitleOverlay.style.padding = "0";
51624
- const S2 = CanvasRenderer.computeSubtitleBottomPadding(l2), I2 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : S2;
51625
- this.subtitleOverlay.style.paddingBottom = `${I2}px`, this.subtitleOverlay.style.textAlign = "center", this.subtitleOverlay.style.boxSizing = "border-box", this.subtitleOverlay.style.margin = "0";
51626
- let q2 = this.subtitleOverlay.querySelector("img.movi-subtitle-image");
51627
- if (v.debug(Y, `Rendering image subtitle in overlay: ${q2 ? "img exists" : "creating img"}, x=${T2.toFixed(0)}, y=${B2.toFixed(0)}, width=${(A2.image.width * d2).toFixed(0)}, height=${(A2.image.height * c2).toFixed(0)}`), q2 || (q2 = document.createElement("img"), q2.className = "movi-subtitle-image", q2.style.display = "block", q2.style.position = "relative", q2.style.margin = "0", q2.style.padding = "0", q2.style.border = "none", q2.style.outline = "none", this.subtitleOverlay.innerHTML = "", this.subtitleOverlay.appendChild(q2)), A2.position?.x) {
51623
+ T2 = Math.max(0, Math.min(T2, f2 - k2));
51624
+ const S2 = ((this.rotation ?? 0) % 360 + 360) % 360, I2 = 90 === S2 || 270 === S2, q2 = I2 ? l2 : f2, w2 = I2 ? f2 : l2;
51625
+ this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${q2}px`, this.subtitleOverlay.style.height = `${w2}px`, this.subtitleOverlay.style.left = (f2 - q2) / 2 + "px", this.subtitleOverlay.style.top = (l2 - w2) / 2 + "px", this.subtitleOverlay.style.pointerEvents = "none", this.subtitleOverlay.style.transformOrigin = "center center", this.subtitleOverlay.style.transform = S2 ? `rotate(${S2}deg)` : "none", this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.overflow = "hidden", this.subtitleOverlay.style.padding = "0";
51626
+ const $2 = CanvasRenderer.computeSubtitleBottomPadding(w2), N2 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : $2;
51627
+ this.subtitleOverlay.style.paddingBottom = `${N2}px`, this.subtitleOverlay.style.textAlign = "center", this.subtitleOverlay.style.boxSizing = "border-box", this.subtitleOverlay.style.margin = "0";
51628
+ let C2 = this.subtitleOverlay.querySelector("img.movi-subtitle-image");
51629
+ if (v.debug(Y, `Rendering image subtitle in overlay: ${C2 ? "img exists" : "creating img"}, x=${T2.toFixed(0)}, y=${B2.toFixed(0)}, width=${(A2.image.width * d2).toFixed(0)}, height=${(A2.image.height * c2).toFixed(0)}`), C2 || (C2 = document.createElement("img"), C2.className = "movi-subtitle-image", C2.style.display = "block", C2.style.position = "relative", C2.style.margin = "0", C2.style.padding = "0", C2.style.border = "none", C2.style.outline = "none", this.subtitleOverlay.innerHTML = "", this.subtitleOverlay.appendChild(C2)), A2.position?.x) {
51628
51630
  const A3 = T2 - (f2 - k2) / 2;
51629
- q2.style.marginLeft = `${A3}px`, q2.style.marginRight = "0";
51630
- } else q2.style.marginLeft = "auto", q2.style.marginRight = "auto";
51631
- q2.src = b2, q2.style.width = `${k2}px`, q2.style.height = `${g2}px`, q2.style.maxWidth = `${f2}px`, q2.style.maxHeight = `${l2}px`, q2.style.objectFit = "contain", q2.style.display = "block", q2.style.visibility = "visible", q2.style.opacity = "1", v.debug(Y, `Image subtitle rendered: src set, dimensions=${(A2.image.width * d2).toFixed(0)}x${(A2.image.height * c2).toFixed(0)}, position=(${T2.toFixed(0)}, ${B2.toFixed(0)})`);
51631
+ C2.style.marginLeft = `${A3}px`, C2.style.marginRight = "0";
51632
+ } else C2.style.marginLeft = "auto", C2.style.marginRight = "auto";
51633
+ C2.src = b2, C2.style.width = `${k2}px`, C2.style.height = `${g2}px`, C2.style.maxWidth = `${q2}px`, C2.style.maxHeight = `${w2}px`, C2.style.objectFit = "contain", C2.style.display = "block", C2.style.visibility = "visible", C2.style.opacity = "1", v.debug(Y, `Image subtitle rendered: src set, dimensions=${(A2.image.width * d2).toFixed(0)}x${(A2.image.height * c2).toFixed(0)}, position=(${T2.toFixed(0)}, ${B2.toFixed(0)})`);
51632
51634
  } catch (A3) {
51633
51635
  v.error(Y, "Failed to render image subtitle in overlay", A3);
51634
51636
  }
@@ -51665,49 +51667,49 @@ class CanvasRenderer {
51665
51667
  if (n2.image) return this.subtitleOverlay ? void this.renderImageSubtitleInOverlay(n2) : void 0;
51666
51668
  if (this.subtitleOverlay) {
51667
51669
  if (!n2.text) return this.subtitleOverlay.textContent = "", void (this.subtitleOverlay.style.display = "none");
51668
- const A3 = this.canvas instanceof HTMLCanvasElement ? this.canvas : null, b2 = A3?.getBoundingClientRect(), j2 = b2?.width || t2, s2 = b2?.height || v2, f2 = CanvasRenderer.computeSubtitleBottomPadding(s2);
51669
- this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.top = "0", this.subtitleOverlay.style.left = "0", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${j2}px`, this.subtitleOverlay.style.height = `${s2}px`, this.subtitleOverlay.style.margin = "0", this.subtitleOverlay.style.padding = "0";
51670
- const l2 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : f2;
51671
- this.subtitleOverlay.style.paddingBottom = `${l2}px`, this.subtitleOverlay.style.transform = "none", this.subtitleOverlay.style.boxSizing = "border-box", this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.textAlign = "left", this.subtitleOverlay.style.pointerEvents = "none";
51672
- const E2 = `${n2.start.toFixed(3)}|${n2.text}`;
51673
- if (E2 === this._lastRenderedSubtitleKey) return;
51674
- this._lastRenderedSubtitleKey = E2;
51675
- const u2 = "⟨⟨GHOST⟩⟩", d2 = n2.text.indexOf(u2), c2 = d2 >= 0 ? n2.text.slice(0, d2) : n2.text, F2 = d2 >= 0 ? n2.text.slice(d2 + u2.length) : n2.text, h2 = (() => {
51670
+ const A3 = this.canvas instanceof HTMLCanvasElement ? this.canvas : null, b2 = A3?.getBoundingClientRect(), j2 = b2?.width || t2, s2 = b2?.height || v2, f2 = ((this.rotation ?? 0) % 360 + 360) % 360, l2 = 90 === f2 || 270 === f2, E2 = l2 ? s2 : j2, u2 = l2 ? j2 : s2, d2 = CanvasRenderer.computeSubtitleBottomPadding(u2);
51671
+ this.subtitleOverlay.style.position = "absolute", this.subtitleOverlay.style.right = "auto", this.subtitleOverlay.style.bottom = "auto", this.subtitleOverlay.style.width = `${E2}px`, this.subtitleOverlay.style.height = `${u2}px`, this.subtitleOverlay.style.left = (j2 - E2) / 2 + "px", this.subtitleOverlay.style.top = (s2 - u2) / 2 + "px", this.subtitleOverlay.style.margin = "0", this.subtitleOverlay.style.padding = "0";
51672
+ const c2 = this.subtitleControlsPadding > 0 ? this.subtitleControlsPadding : d2;
51673
+ this.subtitleOverlay.style.paddingBottom = `${c2}px`, this.subtitleOverlay.style.transformOrigin = "center center", this.subtitleOverlay.style.transform = f2 ? `rotate(${f2}deg)` : "none", this.subtitleOverlay.style.boxSizing = "border-box", this.subtitleOverlay.style.display = "flex", this.subtitleOverlay.style.flexDirection = "column", this.subtitleOverlay.style.justifyContent = "flex-end", this.subtitleOverlay.style.alignItems = "center", this.subtitleOverlay.style.textAlign = "left", this.subtitleOverlay.style.pointerEvents = "none";
51674
+ const F2 = `${n2.start.toFixed(3)}|${n2.text}`;
51675
+ if (F2 === this._lastRenderedSubtitleKey) return;
51676
+ this._lastRenderedSubtitleKey = F2;
51677
+ const h2 = "⟨⟨GHOST⟩⟩", p2 = n2.text.indexOf(h2), m2 = p2 >= 0 ? n2.text.slice(0, p2) : n2.text, k2 = p2 >= 0 ? n2.text.slice(p2 + h2.length) : n2.text, g2 = (() => {
51676
51678
  const A4 = this._subtitleFontCache;
51677
51679
  if (A4 && A4.viewport === window.innerWidth) return A4.font;
51678
51680
  const t3 = document.createElement("div");
51679
51681
  t3.className = "movi-subtitle-line", t3.style.position = "absolute", t3.style.left = "-99999px", t3.style.top = "-99999px", t3.style.visibility = "hidden", t3.textContent = "M", this.subtitleOverlay.parentNode?.appendChild(t3);
51680
51682
  const v3 = window.getComputedStyle(t3), n3 = `${v3.fontStyle} ${v3.fontWeight} ${v3.fontSize} ${v3.fontFamily}`;
51681
51683
  return t3.remove(), this._subtitleFontCache = { viewport: window.innerWidth, font: n3 }, n3;
51682
- })(), p2 = (A4) => {
51683
- const t3 = A4.indexOf(u2);
51684
+ })(), x2 = (A4) => {
51685
+ const t3 = A4.indexOf(h2);
51684
51686
  return t3 >= 0 ? A4.slice(0, t3) : A4;
51685
51687
  };
51686
- let m2 = F2;
51687
- const k2 = this.subtitleCues.indexOf(this.activeSubtitleCue);
51688
- if (k2 >= 0) {
51689
- let A4 = c2;
51690
- for (let t3 = k2 + 1; t3 < this.subtitleCues.length; t3++) {
51688
+ let y2 = k2;
51689
+ const _2 = this.subtitleCues.indexOf(this.activeSubtitleCue);
51690
+ if (_2 >= 0) {
51691
+ let A4 = m2;
51692
+ for (let t3 = _2 + 1; t3 < this.subtitleCues.length; t3++) {
51691
51693
  const v3 = this.subtitleCues[t3];
51692
51694
  if (!v3?.text) break;
51693
- const n3 = p2(v3.text);
51694
- if (n3.length > A4.length && n3.startsWith(A4)) A4 = n3, m2 = v3.text.length > n3.length ? v3.text : n3;
51695
+ const n3 = x2(v3.text);
51696
+ if (n3.length > A4.length && n3.startsWith(A4)) A4 = n3, y2 = v3.text.length > n3.length ? v3.text : n3;
51695
51697
  else if (!n3.startsWith(A4)) break;
51696
51698
  }
51697
51699
  }
51698
- const g2 = p2(m2).replace(/<[^>]*>/g, ""), x2 = (this._subtitleMeasureCanvas ||= document.createElement("canvas")).getContext("2d");
51699
- let y2 = 0;
51700
- if (x2) {
51701
- x2.font = h2;
51702
- for (const A4 of g2.split("\n")) {
51703
- const t3 = Math.ceil(x2.measureText(A4).width);
51704
- t3 > y2 && (y2 = t3);
51700
+ const T2 = x2(y2).replace(/<[^>]*>/g, ""), B2 = (this._subtitleMeasureCanvas ||= document.createElement("canvas")).getContext("2d");
51701
+ let S2 = 0;
51702
+ if (B2) {
51703
+ B2.font = g2;
51704
+ for (const A4 of T2.split("\n")) {
51705
+ const t3 = Math.ceil(B2.measureText(A4).width);
51706
+ t3 > S2 && (S2 = t3);
51705
51707
  }
51706
51708
  }
51707
- const _2 = c2.split("\n"), T2 = this._lastRenderedSubtitlePlain, B2 = T2 && c2.startsWith(T2) && c2.length > T2.length ? T2.split(/\s+/).filter(Boolean).length : 0;
51708
- this._lastRenderedSubtitlePlain = c2;
51709
- let S2 = 0;
51710
- const I2 = _2.map((A4) => {
51709
+ const I2 = m2.split("\n"), q2 = this._lastRenderedSubtitlePlain, w2 = q2 && m2.startsWith(q2) && m2.length > q2.length ? q2.split(/\s+/).filter(Boolean).length : 0;
51710
+ this._lastRenderedSubtitlePlain = m2;
51711
+ let $2 = 0;
51712
+ const N2 = I2.map((A4) => {
51711
51713
  const t3 = [];
51712
51714
  let v3 = A4.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#0?39;/g, "'").replace(/&#x27;/g, "'").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&");
51713
51715
  v3 = v3.replace(/<(\/?)i>/gi, (A5) => {
@@ -51742,24 +51744,24 @@ class CanvasRenderer {
51742
51744
  }
51743
51745
  const E3 = [], u3 = [];
51744
51746
  for (const A5 of f3) {
51745
- const t4 = (A6) => A6 < B2 ? E3 : u3;
51747
+ const t4 = (A6) => A6 < w2 ? E3 : u3;
51746
51748
  if ("ws" === A5.kind) {
51747
- const v5 = t4(S2);
51748
- if (v5 === E3 && 0 === E3.length && 0 === S2) continue;
51749
+ const v5 = t4($2);
51750
+ if (v5 === E3 && 0 === E3.length && 0 === $2) continue;
51749
51751
  v5.push(A5.text);
51750
51752
  continue;
51751
51753
  }
51752
- const v4 = t4(S2);
51754
+ const v4 = t4($2);
51753
51755
  if (v4 === u3 && 0 === u3.length && E3.length > 0) {
51754
51756
  const A6 = E3[E3.length - 1];
51755
51757
  /\s$/.test(A6) || E3.push(" ");
51756
51758
  }
51757
- v4.push(A5.text), S2 += 1;
51759
+ v4.push(A5.text), $2 += 1;
51758
51760
  }
51759
51761
  const d3 = E3.join("").replace(/\s+$/, " "), c3 = u3.join(""), F3 = ['<div class="movi-subtitle-line">'];
51760
51762
  return d3 && F3.push(`<span class="movi-subtitle-static">${d3}</span>`), c3 && F3.push(`<span class="movi-subtitle-new">${c3}</span>`), F3.push("</div>"), F3.join("");
51761
- }).join(""), q2 = parseFloat(this.subtitleOverlay.style.width) || 0, w2 = q2 > 0 && y2 > 0 && y2 <= 0.92 * q2, $2 = w2 ? Math.max(0, Math.floor((q2 - y2) / 2)) : 0, N2 = w2 ? $2 > 0 ? ` style="padding-left:${$2}px"` : "" : ' style="text-align:center"';
51762
- return void (this.subtitleOverlay.innerHTML = `<div class="movi-subtitle-anchor"${N2}><div class="movi-subtitle-block">${I2}</div></div>`);
51763
+ }).join(""), C2 = parseFloat(this.subtitleOverlay.style.width) || 0, R2 = C2 > 0 && S2 > 0 && S2 <= 0.92 * C2, H2 = R2 ? Math.max(0, Math.floor((C2 - S2) / 2)) : 0, P2 = R2 ? H2 > 0 ? ` style="padding-left:${H2}px"` : "" : ' style="text-align:center"';
51764
+ return void (this.subtitleOverlay.innerHTML = `<div class="movi-subtitle-anchor"${P2}><div class="movi-subtitle-block">${N2}</div></div>`);
51763
51765
  }
51764
51766
  }
51765
51767
  setPlaybackRate(A2) {
@@ -108998,7 +109000,7 @@ class MoviPlayer extends j {
108998
109000
  return this.trackManager.getAudioTracks().length > 0 || this.hasNativeAudio() || null !== this.streamWrapper;
108999
109001
  }
109000
109002
  usesNativeAudio() {
109001
- return null !== this.streamWrapper || this.isNativeAudioActive();
109003
+ return null !== this.streamWrapper || null !== this.nativeAudioEl;
109002
109004
  }
109003
109005
  isLiveStream() {
109004
109006
  return this.streamWrapper?.isLive?.() ?? false;
@@ -109569,6 +109571,7 @@ class MoviElement extends HTMLElement {
109569
109571
  _posterCoverUrl = "";
109570
109572
  _posterCoverLoading = false;
109571
109573
  _coverArtBgEl = null;
109574
+ _coverArtBgUrl = "";
109572
109575
  _coverArtResolved = false;
109573
109576
  _lastStripDispatched = null;
109574
109577
  controlsTimeout = null;
@@ -110523,7 +110526,7 @@ class MoviElement extends HTMLElement {
110523
110526
  if (A2.preventDefault(), this.player && !this._pipWindow) {
110524
110527
  const A3 = this.player.rotateVideo();
110525
110528
  this.showOSD('<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>', `${A3}°`);
110526
- const t3 = this.shadowRoot?.querySelector(".movi-rotate-status");
110529
+ const t3 = this.contextMenuRoot().querySelector(".movi-rotate-status");
110527
110530
  t3 && (t3.textContent = `${A3}°`), this.syncThumbnailRotation(A3);
110528
110531
  }
110529
110532
  break;
@@ -110688,18 +110691,20 @@ class MoviElement extends HTMLElement {
110688
110691
  } else {
110689
110692
  t2.classList.remove("movi-context-menu-mobile");
110690
110693
  const v2 = A2.querySelector(".movi-context-menu-backdrop");
110691
- if (v2 && (v2.style.display = "none"), this.classList.contains("movi-audio-strip")) {
110692
- t2.style.position = "fixed", t2.style.maxHeight = `${Math.max(180, window.innerHeight - 40)}px`, t2.style.display = "block", t2.style.visibility = "hidden";
110694
+ v2 && (v2.style.display = "none");
110695
+ const b4 = this.classList.contains("movi-audio-strip"), j4 = this.isFullscreenActive();
110696
+ if (b4 || j4) {
110697
+ j4 && this.classList.add("movi-menu-overflow"), t2.style.position = "fixed", t2.style.maxHeight = `${Math.max(180, window.innerHeight - 40)}px`, t2.style.display = "block", t2.style.visibility = "hidden";
110693
110698
  const A3 = t2.offsetWidth, v3 = t2.offsetHeight;
110694
110699
  t2.style.visibility = "visible";
110695
- let b5 = n3.clientX, j5 = n3.clientY;
110696
- return b5 + A3 > window.innerWidth && (b5 = window.innerWidth - A3 - 10), b5 < 10 && (b5 = 10), j5 + v3 > window.innerHeight && (j5 = window.innerHeight - v3 - 10), j5 < 10 && (j5 = 10), t2.style.left = `${b5}px`, t2.style.top = `${j5}px`, this.clampMenuToViewport(t2), requestAnimationFrame(() => t2.classList.add("visible")), void (this._contextMenuVisible = true);
110700
+ let b5 = n3.clientX, s5 = n3.clientY;
110701
+ return b5 + A3 > window.innerWidth && (b5 = window.innerWidth - A3 - 10), b5 < 10 && (b5 = 10), s5 + v3 > window.innerHeight && (s5 = window.innerHeight - v3 - 10), s5 < 10 && (s5 = 10), t2.style.left = `${b5}px`, t2.style.top = `${s5}px`, this.clampMenuToViewport(t2), requestAnimationFrame(() => t2.classList.add("visible")), void (this._contextMenuVisible = true);
110697
110702
  }
110698
110703
  this.portalContextMenu(t2), t2.style.position = "fixed";
110699
- let b4 = n3.clientX, j4 = n3.clientY;
110704
+ let s4 = n3.clientX, f4 = n3.clientY;
110700
110705
  t2.style.maxHeight = `${Math.max(180, window.innerHeight - 40)}px`, t2.style.display = "block", t2.style.visibility = "hidden";
110701
- const s4 = t2.offsetWidth, f4 = t2.offsetHeight;
110702
- t2.style.visibility = "visible", b4 + s4 > window.innerWidth - 10 && (b4 -= s4), j4 + f4 > window.innerHeight - 10 && (j4 -= f4), t2.style.left = `${b4}px`, t2.style.top = `${j4}px`, this.clampMenuToViewport(t2);
110706
+ const l3 = t2.offsetWidth, E3 = t2.offsetHeight;
110707
+ t2.style.visibility = "visible", s4 + l3 > window.innerWidth - 10 && (s4 -= l3), f4 + E3 > window.innerHeight - 10 && (f4 -= E3), t2.style.left = `${s4}px`, t2.style.top = `${f4}px`, this.clampMenuToViewport(t2);
110703
110708
  }
110704
110709
  return requestAnimationFrame(() => {
110705
110710
  t2.classList.add("visible");
@@ -110834,8 +110839,8 @@ class MoviElement extends HTMLElement {
110834
110839
  } else if ("hdr-toggle" === j3) this.hdr = !this.hdr, this.showOSD(lj, this.hdr ? "HDR On" : "HDR Off"), b2();
110835
110840
  else if ("rotate-video" === j3) {
110836
110841
  if (this.player && !this._pipWindow) {
110837
- const t3 = this.player.rotateVideo(), v3 = A2.querySelector(".movi-rotate-status");
110838
- v3 && (v3.textContent = `${t3}°`), this.syncThumbnailRotation(t3), this.showOSD('<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>', `Rotate ${t3}°`);
110842
+ const A3 = this.player.rotateVideo(), t3 = this.contextMenuRoot().querySelector(".movi-rotate-status");
110843
+ t3 && (t3.textContent = `${A3}°`), this.syncThumbnailRotation(A3), this.showOSD('<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>', `Rotate ${A3}°`);
110839
110844
  }
110840
110845
  b2();
110841
110846
  } else if ("loop-toggle" === j3) this.loop = !this.loop, this.showOSD(oj, this.loop ? "Loop On" : "Loop Off"), b2();
@@ -116177,7 +116182,7 @@ class MoviElement extends HTMLElement {
116177
116182
  border: 1px solid rgba(255, 255, 255, 0.12);
116178
116183
  border-radius: 16px;
116179
116184
  padding: 8px 4px;
116180
- min-width: 160px;
116185
+ min-width: 230px;
116181
116186
  visibility: hidden;
116182
116187
  opacity: 0;
116183
116188
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
@@ -116207,7 +116212,7 @@ class MoviElement extends HTMLElement {
116207
116212
  border: 1px solid rgba(255, 255, 255, 0.12);
116208
116213
  border-radius: 16px;
116209
116214
  padding: 8px 4px;
116210
- min-width: 160px;
116215
+ min-width: 230px;
116211
116216
  visibility: hidden;
116212
116217
  opacity: 0;
116213
116218
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
@@ -117887,6 +117892,16 @@ class MoviElement extends HTMLElement {
117887
117892
  this._posterCoverUrl === t2 && (this._posterCoverLoading = false, this._posterCoverUrl = "", this.updateCoverArtOverlay());
117888
117893
  }, v2.src = t2;
117889
117894
  }
117895
+ makeCoverArtBgUrl(A2) {
117896
+ try {
117897
+ const t2 = 96, v2 = A2.width / A2.height, n2 = Math.max(1, v2 >= 1 ? t2 : Math.round(t2 * v2)), b2 = Math.max(1, v2 >= 1 ? Math.round(t2 / v2) : t2), j2 = document.createElement("canvas");
117898
+ j2.width = n2, j2.height = b2;
117899
+ const s2 = j2.getContext("2d");
117900
+ return s2 ? (s2.drawImage(A2, 0, 0, n2, b2), j2.toDataURL("image/jpeg", 0.7)) : "";
117901
+ } catch {
117902
+ return "";
117903
+ }
117904
+ }
117890
117905
  updateCoverArtOverlay() {
117891
117906
  const A2 = this.coverArtOverlay, t2 = this.coverArtCanvas;
117892
117907
  if (!A2 || !t2) return;
@@ -117901,7 +117916,7 @@ class MoviElement extends HTMLElement {
117901
117916
  const B2 = t2.getContext("2d");
117902
117917
  if (!B2) return;
117903
117918
  if (B2.save(), B2.scale(y2, y2), this._coverArtBgEl) {
117904
- const A3 = this.coverArtBitmap ? "" : this._posterCoverUrl;
117919
+ const A3 = this.coverArtBitmap ? this._coverArtBgUrl : this._posterCoverUrl;
117905
117920
  this._coverArtBgEl.style.backgroundImage = A3 ? `url("${A3.replace(/"/g, '\\"')}")` : "none";
117906
117921
  }
117907
117922
  B2.clearRect(0, 0, g2, x2);
@@ -118099,12 +118114,12 @@ class MoviElement extends HTMLElement {
118099
118114
  };
118100
118115
  this.player.on("error", u2), this.eventHandlers.set("error", () => this.player?.off("error", u2));
118101
118116
  const d2 = (A3) => {
118102
- this.coverArtBitmap = A3, this._coverArtResolved = true, this.updateCoverArtOverlay(), A3 && (this.setMediaSessionArtworkFromBitmap(A3), this.dispatchEvent(new CustomEvent("coverart", { detail: { bitmap: A3, width: A3.width, height: A3.height }, bubbles: true, composed: true })));
118117
+ this.coverArtBitmap = A3, this._coverArtBgUrl = A3 ? this.makeCoverArtBgUrl(A3) : "", this._coverArtResolved = true, this.updateCoverArtOverlay(), A3 && (this.setMediaSessionArtworkFromBitmap(A3), this.dispatchEvent(new CustomEvent("coverart", { detail: { bitmap: A3, width: A3.width, height: A3.height }, bubbles: true, composed: true })));
118103
118118
  };
118104
118119
  this.player.on("coverart", d2), this.eventHandlers.set("coverart", () => this.player?.off("coverart", d2));
118105
118120
  }
118106
118121
  async load() {
118107
- if (this._titleAutoLoaded = false, this._lastDuration = 0, this.coverArtBitmap = null, this._coverArtResolved = false, this._posterCoverBitmap) try {
118122
+ if (this._titleAutoLoaded = false, this._lastDuration = 0, this.coverArtBitmap = null, this._coverArtBgUrl = "", this._coverArtResolved = false, this._posterCoverBitmap) try {
118108
118123
  this._posterCoverBitmap.close();
118109
118124
  } catch {
118110
118125
  }
@@ -118632,22 +118647,24 @@ class MoviElement extends HTMLElement {
118632
118647
  set loop(A2) {
118633
118648
  this._loop = !!A2, this._loop ? this.setAttribute("loop", "") : this.removeAttribute("loop"), this.updateLoopUI();
118634
118649
  }
118650
+ contextMenuRoot() {
118651
+ return this._menuPortalRoot?.querySelector(".movi-context-menu") ? this._menuPortalRoot : this.shadowRoot;
118652
+ }
118635
118653
  updateLoopUI() {
118636
118654
  const A2 = this.shadowRoot;
118637
118655
  if (!A2) return;
118638
- const t2 = A2.querySelector(".movi-loop-btn"), v2 = A2.querySelector('.movi-context-menu-item[data-action="loop-toggle"]'), n2 = A2.querySelector(".movi-loop-status"), b2 = A2.querySelector(".movi-context-menu-loop-outline"), j2 = A2.querySelector(".movi-context-menu-loop-filled");
118639
- this._loop ? (t2?.classList.add("active"), v2?.classList.add("movi-context-menu-active"), n2 && (n2.textContent = "On"), b2 && (b2.style.display = "none"), j2 && (j2.style.display = "block")) : (t2?.classList.remove("active"), v2?.classList.remove("movi-context-menu-active"), n2 && (n2.textContent = "Off"), b2 && (b2.style.display = "block"), j2 && (j2.style.display = "none"));
118656
+ const t2 = this.contextMenuRoot(), v2 = A2.querySelector(".movi-loop-btn"), n2 = t2.querySelector('.movi-context-menu-item[data-action="loop-toggle"]'), b2 = t2.querySelector(".movi-loop-status"), j2 = t2.querySelector(".movi-context-menu-loop-outline"), s2 = t2.querySelector(".movi-context-menu-loop-filled");
118657
+ this._loop ? (v2?.classList.add("active"), n2?.classList.add("movi-context-menu-active"), b2 && (b2.textContent = "On"), j2 && (j2.style.display = "none"), s2 && (s2.style.display = "block")) : (v2?.classList.remove("active"), n2?.classList.remove("movi-context-menu-active"), b2 && (b2.textContent = "Off"), j2 && (j2.style.display = "block"), s2 && (s2.style.display = "none"));
118640
118658
  }
118641
118659
  updateAmbientUI() {
118642
- const A2 = this.shadowRoot;
118643
- if (!A2) return;
118644
- const t2 = A2.querySelector('.movi-context-menu-item[data-action="ambient-toggle"]'), v2 = A2.querySelector(".movi-ambient-status"), n2 = A2.querySelector(".movi-context-menu-ambient-outline"), b2 = A2.querySelector(".movi-context-menu-ambient-filled");
118660
+ if (!this.shadowRoot) return;
118661
+ const A2 = this.contextMenuRoot(), t2 = A2.querySelector('.movi-context-menu-item[data-action="ambient-toggle"]'), v2 = A2.querySelector(".movi-ambient-status"), n2 = A2.querySelector(".movi-context-menu-ambient-outline"), b2 = A2.querySelector(".movi-context-menu-ambient-filled");
118645
118662
  this._ambientMode ? (t2?.classList.add("movi-context-menu-active"), v2 && (v2.textContent = "On"), n2 && (n2.style.display = "none"), b2 && (b2.style.display = "block")) : (t2?.classList.remove("movi-context-menu-active"), v2 && (v2.textContent = "Off"), n2 && (n2.style.display = "block"), b2 && (b2.style.display = "none"));
118646
118663
  }
118647
118664
  updateStableAudioUI(A2 = this.shadowRoot) {
118648
118665
  if (!A2) return;
118649
- const t2 = this.player?.getStableAudio() ?? true, v2 = A2.querySelector(".movi-stable-audio-btn"), n2 = A2.querySelector('.movi-context-menu-item[data-action="stable-audio-toggle"]'), b2 = A2.querySelector(".movi-stable-audio-status"), j2 = A2.querySelector(".movi-context-menu-stable-outline"), s2 = A2.querySelector(".movi-context-menu-stable-filled");
118650
- t2 ? (v2?.classList.add("active"), n2?.classList.add("movi-context-menu-active"), b2 && (b2.textContent = "On"), j2 && (j2.style.display = "none"), s2 && (s2.style.display = "block")) : (v2?.classList.remove("active"), n2?.classList.remove("movi-context-menu-active"), b2 && (b2.textContent = "Off"), j2 && (j2.style.display = "block"), s2 && (s2.style.display = "none"));
118666
+ const t2 = this.player?.getStableAudio() ?? true, v2 = this.contextMenuRoot(), n2 = A2.querySelector(".movi-stable-audio-btn"), b2 = v2.querySelector('.movi-context-menu-item[data-action="stable-audio-toggle"]'), j2 = v2.querySelector(".movi-stable-audio-status"), s2 = v2.querySelector(".movi-context-menu-stable-outline"), f2 = v2.querySelector(".movi-context-menu-stable-filled");
118667
+ t2 ? (n2?.classList.add("active"), b2?.classList.add("movi-context-menu-active"), j2 && (j2.textContent = "On"), s2 && (s2.style.display = "none"), f2 && (f2.style.display = "block")) : (n2?.classList.remove("active"), b2?.classList.remove("movi-context-menu-active"), j2 && (j2.textContent = "Off"), s2 && (s2.style.display = "block"), f2 && (f2.style.display = "none"));
118651
118668
  }
118652
118669
  toggleNerdStats(A2 = this.shadowRoot) {
118653
118670
  if (!A2) return;
@@ -119215,8 +119232,8 @@ class MoviElement extends HTMLElement {
119215
119232
  return !!this.player?.isHDRSupported?.();
119216
119233
  }
119217
119234
  updateHDRUI() {
119218
- const A2 = this.shadowRoot?.querySelector(".movi-hdr-btn"), t2 = this.shadowRoot?.querySelector(".movi-hdr-status"), v2 = this.shadowRoot?.querySelector('.movi-context-menu-item[data-action="hdr-toggle"]');
119219
- this._hdr ? (A2?.classList.add("movi-hdr-active"), v2?.classList.add("movi-context-menu-active"), t2 && (t2.textContent = "On")) : (A2?.classList.remove("movi-hdr-active"), v2?.classList.remove("movi-context-menu-active"), t2 && (t2.textContent = "Off"));
119235
+ const A2 = this.contextMenuRoot(), t2 = this.shadowRoot?.querySelector(".movi-hdr-btn"), v2 = A2.querySelector(".movi-hdr-status"), n2 = A2.querySelector('.movi-context-menu-item[data-action="hdr-toggle"]');
119236
+ this._hdr ? (t2?.classList.add("movi-hdr-active"), n2?.classList.add("movi-context-menu-active"), v2 && (v2.textContent = "On")) : (t2?.classList.remove("movi-hdr-active"), n2?.classList.remove("movi-context-menu-active"), v2 && (v2.textContent = "Off"));
119220
119237
  }
119221
119238
  async takeSnapshot() {
119222
119239
  if (this.player) try {