@mottosports/motto-video-player 1.0.1-rc.17 → 1.0.1-rc.18

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/index.mjs CHANGED
@@ -1173,7 +1173,7 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
1173
1173
  if (!playerRef.current) return [];
1174
1174
  const tracks = playerRef.current.getVariantTracks();
1175
1175
  const qualities = tracks.filter(
1176
- (track, index, self) => index === self.findIndex((t) => t.height === track.height)
1176
+ (track, index, self2) => index === self2.findIndex((t) => t.height === track.height)
1177
1177
  ).map((track) => ({
1178
1178
  height: track.height || 0,
1179
1179
  bandwidth: track.bandwidth || 0,
@@ -1702,8 +1702,9 @@ import { useEffect, useState, useRef as useRef5 } from "react";
1702
1702
  var useLiveBadge = (playerRef, options = {}) => {
1703
1703
  const [isLive, setIsLive] = useState(false);
1704
1704
  const [isVisible, setIsVisible] = useState(false);
1705
+ const [isNearLiveEdge, setIsNearLiveEdge] = useState(false);
1705
1706
  const intervalRef = useRef5(null);
1706
- const { enabled = true, onLiveStateChange } = options;
1707
+ const { enabled = true, onLiveStateChange, liveThresholdSeconds = 15 } = options;
1707
1708
  const checkLiveStatus = () => {
1708
1709
  if (!playerRef.current || !enabled) {
1709
1710
  return;
@@ -1722,11 +1723,30 @@ var useLiveBadge = (playerRef, options = {}) => {
1722
1723
  return;
1723
1724
  }
1724
1725
  const liveStatus = timeline.isLive();
1726
+ let nearLiveEdge = false;
1727
+ if (liveStatus) {
1728
+ try {
1729
+ const seekRange = player.getSeekRange();
1730
+ const videoElement = player.getMediaElement();
1731
+ if (seekRange && videoElement) {
1732
+ const liveEdge = seekRange.end;
1733
+ const currentTime = videoElement.currentTime;
1734
+ const timeBehindLive = liveEdge - currentTime;
1735
+ nearLiveEdge = timeBehindLive <= liveThresholdSeconds;
1736
+ }
1737
+ } catch (error) {
1738
+ console.error("Error checking live edge position:", error);
1739
+ nearLiveEdge = liveStatus;
1740
+ }
1741
+ }
1725
1742
  if (liveStatus !== isLive) {
1726
1743
  setIsLive(liveStatus);
1727
- setIsVisible(liveStatus);
1728
1744
  onLiveStateChange?.(liveStatus);
1729
1745
  }
1746
+ if (nearLiveEdge !== isNearLiveEdge) {
1747
+ setIsNearLiveEdge(nearLiveEdge);
1748
+ setIsVisible(nearLiveEdge);
1749
+ }
1730
1750
  } catch (error) {
1731
1751
  if (error instanceof Error && !error.message.includes("not a function")) {
1732
1752
  console.error("Error checking live status:", error);
@@ -1737,17 +1757,18 @@ var useLiveBadge = (playerRef, options = {}) => {
1737
1757
  if (!enabled) {
1738
1758
  setIsLive(false);
1739
1759
  setIsVisible(false);
1760
+ setIsNearLiveEdge(false);
1740
1761
  return;
1741
1762
  }
1742
1763
  checkLiveStatus();
1743
- intervalRef.current = setInterval(checkLiveStatus, 2e3);
1764
+ intervalRef.current = setInterval(checkLiveStatus, 1e3);
1744
1765
  return () => {
1745
1766
  if (intervalRef.current) {
1746
1767
  clearInterval(intervalRef.current);
1747
1768
  intervalRef.current = null;
1748
1769
  }
1749
1770
  };
1750
- }, [enabled, playerRef.current]);
1771
+ }, [enabled, playerRef.current, liveThresholdSeconds]);
1751
1772
  useEffect(() => {
1752
1773
  return () => {
1753
1774
  if (intervalRef.current) {
@@ -1760,6 +1781,7 @@ var useLiveBadge = (playerRef, options = {}) => {
1760
1781
  return {
1761
1782
  isLive,
1762
1783
  isVisible,
1784
+ isNearLiveEdge,
1763
1785
  hideBadge,
1764
1786
  showBadge,
1765
1787
  checkLiveStatus
@@ -1771,16 +1793,48 @@ import { useEffect as useEffect2, useState as useState2 } from "react";
1771
1793
 
1772
1794
  // src/hooks/useLiveIndicator.ts
1773
1795
  import { useEffect as useEffect3, useRef as useRef7 } from "react";
1774
- var useLiveIndicator = (containerRef, options = {}) => {
1796
+ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1775
1797
  const observerRef = useRef7(null);
1798
+ const intervalRef = useRef7(null);
1776
1799
  const {
1777
1800
  enabled = true,
1778
1801
  indicatorColor = "#ff0000",
1779
1802
  indicatorSize = 8,
1780
- showPulseAnimation = true
1803
+ showPulseAnimation = true,
1804
+ liveThresholdSeconds = 15
1781
1805
  } = options;
1806
+ const isNearLiveEdge = (player) => {
1807
+ if (!player) return false;
1808
+ try {
1809
+ if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
1810
+ return false;
1811
+ }
1812
+ const manifest = player.getManifest();
1813
+ if (!manifest) {
1814
+ return false;
1815
+ }
1816
+ const timeline = player.getPresentationTimeline();
1817
+ if (!timeline || typeof timeline.isLive !== "function") {
1818
+ return false;
1819
+ }
1820
+ const liveStatus = timeline.isLive();
1821
+ if (!liveStatus) return false;
1822
+ const seekRange = player.getSeekRange();
1823
+ const videoElement = player.getMediaElement();
1824
+ if (seekRange && videoElement) {
1825
+ const liveEdge = seekRange.end;
1826
+ const currentTime = videoElement.currentTime;
1827
+ const timeBehindLive = liveEdge - currentTime;
1828
+ return timeBehindLive <= liveThresholdSeconds;
1829
+ }
1830
+ return false;
1831
+ } catch (error) {
1832
+ console.error("Error checking live edge position in indicator:", error);
1833
+ return false;
1834
+ }
1835
+ };
1782
1836
  useEffect3(() => {
1783
- if (!containerRef.current || !enabled) {
1837
+ if (!containerRef.current || !playerRef.current || !enabled) {
1784
1838
  return;
1785
1839
  }
1786
1840
  const addLiveIndicator = (currentTimeElement) => {
@@ -1811,7 +1865,7 @@ var useLiveIndicator = (containerRef, options = {}) => {
1811
1865
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1812
1866
  currentTimeElements?.forEach((element) => {
1813
1867
  const textContent = element.textContent?.trim() || "";
1814
- if (textContent.toLowerCase().includes("live")) {
1868
+ if (textContent.toLowerCase().includes("live") && isNearLiveEdge(playerRef.current)) {
1815
1869
  addLiveIndicator(element);
1816
1870
  } else {
1817
1871
  removeLiveIndicator(element);
@@ -1819,6 +1873,7 @@ var useLiveIndicator = (containerRef, options = {}) => {
1819
1873
  });
1820
1874
  };
1821
1875
  checkForLiveContent();
1876
+ intervalRef.current = setInterval(checkForLiveContent, 1e3);
1822
1877
  observerRef.current = new MutationObserver((mutations) => {
1823
1878
  let shouldCheck = false;
1824
1879
  mutations.forEach((mutation) => {
@@ -1848,15 +1903,18 @@ var useLiveIndicator = (containerRef, options = {}) => {
1848
1903
  if (observerRef.current) {
1849
1904
  observerRef.current.disconnect();
1850
1905
  }
1906
+ if (intervalRef.current) {
1907
+ clearInterval(intervalRef.current);
1908
+ }
1851
1909
  };
1852
- }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
1910
+ }, [containerRef, playerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
1853
1911
  return {
1854
1912
  // Expose method to manually trigger check if needed
1855
1913
  checkForLiveContent: () => {
1856
1914
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1857
1915
  currentTimeElements?.forEach((element) => {
1858
1916
  const textContent = element.textContent?.trim() || "";
1859
- if (textContent.toLowerCase().includes("live")) {
1917
+ if (textContent.toLowerCase().includes("live") && isNearLiveEdge(playerRef.current)) {
1860
1918
  }
1861
1919
  });
1862
1920
  }
@@ -3166,15 +3224,17 @@ var Player = forwardRef(
3166
3224
  );
3167
3225
  const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
3168
3226
  enabled: true,
3227
+ liveThresholdSeconds: 15,
3169
3228
  onLiveStateChange: (isLive2) => {
3170
3229
  events?.onLiveStateChange?.(isLive2);
3171
3230
  }
3172
3231
  });
3173
- useLiveIndicator(containerRef, {
3232
+ useLiveIndicator(containerRef, playerRef, {
3174
3233
  enabled: true,
3175
3234
  indicatorColor: "#ff0000",
3176
3235
  indicatorSize: 8,
3177
- showPulseAnimation: true
3236
+ showPulseAnimation: true,
3237
+ liveThresholdSeconds: 15
3178
3238
  });
3179
3239
  const initializeAds = () => {
3180
3240
  if (!imaConfig || !playerRef.current || !videoRef.current) return;
@@ -3806,8 +3866,37 @@ var useMessages = (locale) => {
3806
3866
  };
3807
3867
  var useMessages_default = useMessages;
3808
3868
 
3869
+ // src/utils/crypto-polyfill.ts
3870
+ function polyfillCryptoRandomUUID() {
3871
+ if (typeof globalThis !== "undefined" && globalThis.crypto && !globalThis.crypto.randomUUID) {
3872
+ globalThis.crypto.randomUUID = generateRandomUUID;
3873
+ }
3874
+ if (typeof window !== "undefined" && window.crypto && !window.crypto.randomUUID) {
3875
+ window.crypto.randomUUID = generateRandomUUID;
3876
+ }
3877
+ if (typeof self !== "undefined" && self.crypto && !self.crypto.randomUUID) {
3878
+ self.crypto.randomUUID = generateRandomUUID;
3879
+ }
3880
+ }
3881
+ function generateRandomUUID() {
3882
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
3883
+ const array = new Uint8Array(16);
3884
+ crypto.getRandomValues(array);
3885
+ array[6] = array[6] & 15 | 64;
3886
+ array[8] = array[8] & 63 | 128;
3887
+ const hex = Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
3888
+ return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20, 32)}`;
3889
+ }
3890
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
3891
+ const r = Math.random() * 16 | 0;
3892
+ const v = c === "x" ? r : r & 3 | 8;
3893
+ return v.toString(16);
3894
+ });
3895
+ }
3896
+
3809
3897
  // src/Video.tsx
3810
3898
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
3899
+ polyfillCryptoRandomUUID();
3811
3900
  var Video = ({
3812
3901
  videoId,
3813
3902
  publicKey,
@@ -3898,6 +3987,7 @@ import { useCallback as useCallback8, useEffect as useEffect8, useState as useSt
3898
3987
  import { twMerge as twMerge4 } from "tailwind-merge";
3899
3988
  import { useQuery as useQuery2 } from "@tanstack/react-query";
3900
3989
  import { Fragment, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
3990
+ polyfillCryptoRandomUUID();
3901
3991
  var Event = ({
3902
3992
  publicKey,
3903
3993
  eventId,
@@ -4224,6 +4314,7 @@ import { useEffect as useEffect9, useState as useState5 } from "react";
4224
4314
  import { twMerge as twMerge5 } from "tailwind-merge";
4225
4315
  import { useQuery as useQuery3 } from "@tanstack/react-query";
4226
4316
  import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
4317
+ polyfillCryptoRandomUUID();
4227
4318
  var CreativeWork = ({
4228
4319
  publicKey,
4229
4320
  creativeWorkId,
@@ -4575,6 +4666,7 @@ export {
4575
4666
  SkipBackIcon,
4576
4667
  SkipForwardIcon,
4577
4668
  Video,
4669
+ polyfillCryptoRandomUUID,
4578
4670
  queryClient
4579
4671
  };
4580
4672
  //# sourceMappingURL=index.mjs.map