@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.d.mts CHANGED
@@ -521,4 +521,6 @@ interface BigPlayIconProps {
521
521
  }
522
522
  declare const BigPlayIcon: React.FC<BigPlayIconProps>;
523
523
 
524
- export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoListItem, type VideoProps, queryClient };
524
+ declare function polyfillCryptoRandomUUID(): void;
525
+
526
+ export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoListItem, type VideoProps, polyfillCryptoRandomUUID, queryClient };
package/dist/index.d.ts CHANGED
@@ -521,4 +521,6 @@ interface BigPlayIconProps {
521
521
  }
522
522
  declare const BigPlayIcon: React.FC<BigPlayIconProps>;
523
523
 
524
- export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoListItem, type VideoProps, queryClient };
524
+ declare function polyfillCryptoRandomUUID(): void;
525
+
526
+ export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoListItem, type VideoProps, polyfillCryptoRandomUUID, queryClient };
package/dist/index.js CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  SkipBackIcon: () => SkipBackIcon,
40
40
  SkipForwardIcon: () => SkipForwardIcon,
41
41
  Video: () => Video,
42
+ polyfillCryptoRandomUUID: () => polyfillCryptoRandomUUID,
42
43
  queryClient: () => queryClient
43
44
  });
44
45
  module.exports = __toCommonJS(index_exports);
@@ -1214,7 +1215,7 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
1214
1215
  if (!playerRef.current) return [];
1215
1216
  const tracks = playerRef.current.getVariantTracks();
1216
1217
  const qualities = tracks.filter(
1217
- (track, index, self) => index === self.findIndex((t) => t.height === track.height)
1218
+ (track, index, self2) => index === self2.findIndex((t) => t.height === track.height)
1218
1219
  ).map((track) => ({
1219
1220
  height: track.height || 0,
1220
1221
  bandwidth: track.bandwidth || 0,
@@ -1743,8 +1744,9 @@ var import_react8 = require("react");
1743
1744
  var useLiveBadge = (playerRef, options = {}) => {
1744
1745
  const [isLive, setIsLive] = (0, import_react8.useState)(false);
1745
1746
  const [isVisible, setIsVisible] = (0, import_react8.useState)(false);
1747
+ const [isNearLiveEdge, setIsNearLiveEdge] = (0, import_react8.useState)(false);
1746
1748
  const intervalRef = (0, import_react8.useRef)(null);
1747
- const { enabled = true, onLiveStateChange } = options;
1749
+ const { enabled = true, onLiveStateChange, liveThresholdSeconds = 15 } = options;
1748
1750
  const checkLiveStatus = () => {
1749
1751
  if (!playerRef.current || !enabled) {
1750
1752
  return;
@@ -1763,11 +1765,30 @@ var useLiveBadge = (playerRef, options = {}) => {
1763
1765
  return;
1764
1766
  }
1765
1767
  const liveStatus = timeline.isLive();
1768
+ let nearLiveEdge = false;
1769
+ if (liveStatus) {
1770
+ try {
1771
+ const seekRange = player.getSeekRange();
1772
+ const videoElement = player.getMediaElement();
1773
+ if (seekRange && videoElement) {
1774
+ const liveEdge = seekRange.end;
1775
+ const currentTime = videoElement.currentTime;
1776
+ const timeBehindLive = liveEdge - currentTime;
1777
+ nearLiveEdge = timeBehindLive <= liveThresholdSeconds;
1778
+ }
1779
+ } catch (error) {
1780
+ console.error("Error checking live edge position:", error);
1781
+ nearLiveEdge = liveStatus;
1782
+ }
1783
+ }
1766
1784
  if (liveStatus !== isLive) {
1767
1785
  setIsLive(liveStatus);
1768
- setIsVisible(liveStatus);
1769
1786
  onLiveStateChange?.(liveStatus);
1770
1787
  }
1788
+ if (nearLiveEdge !== isNearLiveEdge) {
1789
+ setIsNearLiveEdge(nearLiveEdge);
1790
+ setIsVisible(nearLiveEdge);
1791
+ }
1771
1792
  } catch (error) {
1772
1793
  if (error instanceof Error && !error.message.includes("not a function")) {
1773
1794
  console.error("Error checking live status:", error);
@@ -1778,17 +1799,18 @@ var useLiveBadge = (playerRef, options = {}) => {
1778
1799
  if (!enabled) {
1779
1800
  setIsLive(false);
1780
1801
  setIsVisible(false);
1802
+ setIsNearLiveEdge(false);
1781
1803
  return;
1782
1804
  }
1783
1805
  checkLiveStatus();
1784
- intervalRef.current = setInterval(checkLiveStatus, 2e3);
1806
+ intervalRef.current = setInterval(checkLiveStatus, 1e3);
1785
1807
  return () => {
1786
1808
  if (intervalRef.current) {
1787
1809
  clearInterval(intervalRef.current);
1788
1810
  intervalRef.current = null;
1789
1811
  }
1790
1812
  };
1791
- }, [enabled, playerRef.current]);
1813
+ }, [enabled, playerRef.current, liveThresholdSeconds]);
1792
1814
  (0, import_react8.useEffect)(() => {
1793
1815
  return () => {
1794
1816
  if (intervalRef.current) {
@@ -1801,6 +1823,7 @@ var useLiveBadge = (playerRef, options = {}) => {
1801
1823
  return {
1802
1824
  isLive,
1803
1825
  isVisible,
1826
+ isNearLiveEdge,
1804
1827
  hideBadge,
1805
1828
  showBadge,
1806
1829
  checkLiveStatus
@@ -1812,16 +1835,48 @@ var import_react9 = require("react");
1812
1835
 
1813
1836
  // src/hooks/useLiveIndicator.ts
1814
1837
  var import_react10 = require("react");
1815
- var useLiveIndicator = (containerRef, options = {}) => {
1838
+ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1816
1839
  const observerRef = (0, import_react10.useRef)(null);
1840
+ const intervalRef = (0, import_react10.useRef)(null);
1817
1841
  const {
1818
1842
  enabled = true,
1819
1843
  indicatorColor = "#ff0000",
1820
1844
  indicatorSize = 8,
1821
- showPulseAnimation = true
1845
+ showPulseAnimation = true,
1846
+ liveThresholdSeconds = 15
1822
1847
  } = options;
1848
+ const isNearLiveEdge = (player) => {
1849
+ if (!player) return false;
1850
+ try {
1851
+ if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
1852
+ return false;
1853
+ }
1854
+ const manifest = player.getManifest();
1855
+ if (!manifest) {
1856
+ return false;
1857
+ }
1858
+ const timeline = player.getPresentationTimeline();
1859
+ if (!timeline || typeof timeline.isLive !== "function") {
1860
+ return false;
1861
+ }
1862
+ const liveStatus = timeline.isLive();
1863
+ if (!liveStatus) return false;
1864
+ const seekRange = player.getSeekRange();
1865
+ const videoElement = player.getMediaElement();
1866
+ if (seekRange && videoElement) {
1867
+ const liveEdge = seekRange.end;
1868
+ const currentTime = videoElement.currentTime;
1869
+ const timeBehindLive = liveEdge - currentTime;
1870
+ return timeBehindLive <= liveThresholdSeconds;
1871
+ }
1872
+ return false;
1873
+ } catch (error) {
1874
+ console.error("Error checking live edge position in indicator:", error);
1875
+ return false;
1876
+ }
1877
+ };
1823
1878
  (0, import_react10.useEffect)(() => {
1824
- if (!containerRef.current || !enabled) {
1879
+ if (!containerRef.current || !playerRef.current || !enabled) {
1825
1880
  return;
1826
1881
  }
1827
1882
  const addLiveIndicator = (currentTimeElement) => {
@@ -1852,7 +1907,7 @@ var useLiveIndicator = (containerRef, options = {}) => {
1852
1907
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1853
1908
  currentTimeElements?.forEach((element) => {
1854
1909
  const textContent = element.textContent?.trim() || "";
1855
- if (textContent.toLowerCase().includes("live")) {
1910
+ if (textContent.toLowerCase().includes("live") && isNearLiveEdge(playerRef.current)) {
1856
1911
  addLiveIndicator(element);
1857
1912
  } else {
1858
1913
  removeLiveIndicator(element);
@@ -1860,6 +1915,7 @@ var useLiveIndicator = (containerRef, options = {}) => {
1860
1915
  });
1861
1916
  };
1862
1917
  checkForLiveContent();
1918
+ intervalRef.current = setInterval(checkForLiveContent, 1e3);
1863
1919
  observerRef.current = new MutationObserver((mutations) => {
1864
1920
  let shouldCheck = false;
1865
1921
  mutations.forEach((mutation) => {
@@ -1889,15 +1945,18 @@ var useLiveIndicator = (containerRef, options = {}) => {
1889
1945
  if (observerRef.current) {
1890
1946
  observerRef.current.disconnect();
1891
1947
  }
1948
+ if (intervalRef.current) {
1949
+ clearInterval(intervalRef.current);
1950
+ }
1892
1951
  };
1893
- }, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
1952
+ }, [containerRef, playerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
1894
1953
  return {
1895
1954
  // Expose method to manually trigger check if needed
1896
1955
  checkForLiveContent: () => {
1897
1956
  const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
1898
1957
  currentTimeElements?.forEach((element) => {
1899
1958
  const textContent = element.textContent?.trim() || "";
1900
- if (textContent.toLowerCase().includes("live")) {
1959
+ if (textContent.toLowerCase().includes("live") && isNearLiveEdge(playerRef.current)) {
1901
1960
  }
1902
1961
  });
1903
1962
  }
@@ -3207,15 +3266,17 @@ var Player = (0, import_react12.forwardRef)(
3207
3266
  );
3208
3267
  const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
3209
3268
  enabled: true,
3269
+ liveThresholdSeconds: 15,
3210
3270
  onLiveStateChange: (isLive2) => {
3211
3271
  events?.onLiveStateChange?.(isLive2);
3212
3272
  }
3213
3273
  });
3214
- useLiveIndicator(containerRef, {
3274
+ useLiveIndicator(containerRef, playerRef, {
3215
3275
  enabled: true,
3216
3276
  indicatorColor: "#ff0000",
3217
3277
  indicatorSize: 8,
3218
- showPulseAnimation: true
3278
+ showPulseAnimation: true,
3279
+ liveThresholdSeconds: 15
3219
3280
  });
3220
3281
  const initializeAds = () => {
3221
3282
  if (!imaConfig || !playerRef.current || !videoRef.current) return;
@@ -3847,8 +3908,37 @@ var useMessages = (locale) => {
3847
3908
  };
3848
3909
  var useMessages_default = useMessages;
3849
3910
 
3911
+ // src/utils/crypto-polyfill.ts
3912
+ function polyfillCryptoRandomUUID() {
3913
+ if (typeof globalThis !== "undefined" && globalThis.crypto && !globalThis.crypto.randomUUID) {
3914
+ globalThis.crypto.randomUUID = generateRandomUUID;
3915
+ }
3916
+ if (typeof window !== "undefined" && window.crypto && !window.crypto.randomUUID) {
3917
+ window.crypto.randomUUID = generateRandomUUID;
3918
+ }
3919
+ if (typeof self !== "undefined" && self.crypto && !self.crypto.randomUUID) {
3920
+ self.crypto.randomUUID = generateRandomUUID;
3921
+ }
3922
+ }
3923
+ function generateRandomUUID() {
3924
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
3925
+ const array = new Uint8Array(16);
3926
+ crypto.getRandomValues(array);
3927
+ array[6] = array[6] & 15 | 64;
3928
+ array[8] = array[8] & 63 | 128;
3929
+ const hex = Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
3930
+ return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20, 32)}`;
3931
+ }
3932
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
3933
+ const r = Math.random() * 16 | 0;
3934
+ const v = c === "x" ? r : r & 3 | 8;
3935
+ return v.toString(16);
3936
+ });
3937
+ }
3938
+
3850
3939
  // src/Video.tsx
3851
3940
  var import_jsx_runtime9 = require("react/jsx-runtime");
3941
+ polyfillCryptoRandomUUID();
3852
3942
  var Video = ({
3853
3943
  videoId,
3854
3944
  publicKey,
@@ -3939,6 +4029,7 @@ var import_react15 = require("react");
3939
4029
  var import_tailwind_merge4 = require("tailwind-merge");
3940
4030
  var import_react_query2 = require("@tanstack/react-query");
3941
4031
  var import_jsx_runtime10 = require("react/jsx-runtime");
4032
+ polyfillCryptoRandomUUID();
3942
4033
  var Event = ({
3943
4034
  publicKey,
3944
4035
  eventId,
@@ -4265,6 +4356,7 @@ var import_react16 = require("react");
4265
4356
  var import_tailwind_merge5 = require("tailwind-merge");
4266
4357
  var import_react_query3 = require("@tanstack/react-query");
4267
4358
  var import_jsx_runtime11 = require("react/jsx-runtime");
4359
+ polyfillCryptoRandomUUID();
4268
4360
  var CreativeWork = ({
4269
4361
  publicKey,
4270
4362
  creativeWorkId,
@@ -4617,6 +4709,7 @@ var QueryProvider = ({ children }) => {
4617
4709
  SkipBackIcon,
4618
4710
  SkipForwardIcon,
4619
4711
  Video,
4712
+ polyfillCryptoRandomUUID,
4620
4713
  queryClient
4621
4714
  });
4622
4715
  //# sourceMappingURL=index.js.map