@mottosports/motto-video-player 1.0.1-rc.52 → 1.0.1-rc.54

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
@@ -1115,7 +1115,7 @@ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:fir
1115
1115
  `);
1116
1116
 
1117
1117
  // src/Player.tsx
1118
- import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle, useCallback as useCallback8 } from "react";
1118
+ import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle, useCallback as useCallback8, useState as useState4 } from "react";
1119
1119
  import shaka3 from "shaka-player/dist/shaka-player.ui";
1120
1120
 
1121
1121
  // src/hooks/useShakaPlayer.ts
@@ -1170,7 +1170,7 @@ var supportsWidevinePersistentLicenses = () => {
1170
1170
  import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
1171
1171
 
1172
1172
  // package.json
1173
- var version = "1.0.1-rc.52";
1173
+ var version = "1.0.1-rc.54";
1174
1174
 
1175
1175
  // src/utils/licenseCache.ts
1176
1176
  var PERSISTENT_LICENSE_PREFIX = "motto_lic_";
@@ -1959,7 +1959,7 @@ var SkipForwardButtonFactory = class {
1959
1959
  return new SkipForwardButton(rootElement, controls, this.onSkipForward, this.iconSize);
1960
1960
  }
1961
1961
  };
1962
- var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes) => {
1962
+ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale = "en") => {
1963
1963
  const uiRef = useRef4(null);
1964
1964
  const registeredElements = useRef4(/* @__PURE__ */ new Set());
1965
1965
  const initializeUI = useCallback5(async () => {
@@ -1976,6 +1976,14 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1976
1976
  }
1977
1977
  const ui = new ShakaUI.Overlay(playerRef.current, containerRef.current, videoRef.current);
1978
1978
  uiRef.current = ui;
1979
+ if (locale !== "en") {
1980
+ try {
1981
+ ui.getControls().getLocalization().changeLocale([locale]);
1982
+ console.log(`Set locale to '${locale}'`);
1983
+ } catch (error) {
1984
+ console.warn(`Failed to set locale to '${locale}', falling back to 'en':`, error);
1985
+ }
1986
+ }
1979
1987
  const isMobile = window.innerWidth <= 767;
1980
1988
  const controlPanelElements = [
1981
1989
  ...isMobile ? [] : ["skip_back_button"],
@@ -2040,7 +2048,7 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
2040
2048
  }
2041
2049
  }
2042
2050
  return ui;
2043
- }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes]);
2051
+ }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale]);
2044
2052
  const destroyUI = useCallback5(() => {
2045
2053
  if (uiRef.current) {
2046
2054
  try {
@@ -3557,6 +3565,81 @@ html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:fir
3557
3565
 
3558
3566
  // src/Player.tsx
3559
3567
  import { twMerge as twMerge2 } from "tailwind-merge";
3568
+
3569
+ // src/utils/scriptLoader.ts
3570
+ var SCRIPT_CONFIGS = {
3571
+ ima: {
3572
+ src: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
3573
+ id: "ima-sdk",
3574
+ type: "text/javascript"
3575
+ },
3576
+ system73: {
3577
+ src: "//cdn.s73cloud.com/4/s73-sdk-shakaplayer.js",
3578
+ id: "system73-sdk",
3579
+ type: "application/javascript"
3580
+ }
3581
+ };
3582
+ function loadScript(config) {
3583
+ return new Promise((resolve, reject) => {
3584
+ if (document.getElementById(config.id)) {
3585
+ resolve();
3586
+ return;
3587
+ }
3588
+ const script = document.createElement("script");
3589
+ script.id = config.id;
3590
+ script.src = config.src;
3591
+ script.type = config.type || "text/javascript";
3592
+ script.async = true;
3593
+ script.onload = () => resolve();
3594
+ script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
3595
+ document.head.appendChild(script);
3596
+ });
3597
+ }
3598
+ function getRequiredScriptLoaders(needsIma, needsSystem73) {
3599
+ const loaders = [];
3600
+ if (needsIma) {
3601
+ loaders.push(loadScript(SCRIPT_CONFIGS.ima));
3602
+ }
3603
+ if (needsSystem73) {
3604
+ loaders.push(loadScript(SCRIPT_CONFIGS.system73));
3605
+ }
3606
+ return loaders;
3607
+ }
3608
+ async function loadScripts(scriptLoaders) {
3609
+ if (scriptLoaders.length === 0) {
3610
+ return;
3611
+ }
3612
+ try {
3613
+ await Promise.all(scriptLoaders);
3614
+ } catch (error) {
3615
+ console.error("Error loading scripts:", error);
3616
+ throw error;
3617
+ }
3618
+ }
3619
+ function waitForGlobal(globalName, timeout = 5e3) {
3620
+ return new Promise((resolve, reject) => {
3621
+ const startTime = Date.now();
3622
+ function checkGlobal() {
3623
+ const global = window[globalName];
3624
+ if (global) {
3625
+ resolve(global);
3626
+ return;
3627
+ }
3628
+ if (Date.now() - startTime > timeout) {
3629
+ reject(new Error(`Timeout waiting for global: ${globalName}`));
3630
+ return;
3631
+ }
3632
+ setTimeout(checkGlobal, 100);
3633
+ }
3634
+ checkGlobal();
3635
+ });
3636
+ }
3637
+ async function waitForGlobals(globalNames, timeout = 5e3) {
3638
+ const promises = globalNames.map((name) => waitForGlobal(name, timeout));
3639
+ await Promise.all(promises);
3640
+ }
3641
+
3642
+ // src/Player.tsx
3560
3643
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
3561
3644
  var Player = forwardRef(
3562
3645
  ({
@@ -3579,12 +3662,13 @@ var Player = forwardRef(
3579
3662
  seekbarConfig,
3580
3663
  iconSizes,
3581
3664
  events,
3665
+ locale = "en",
3582
3666
  containerClassName,
3583
3667
  ...videoProps
3584
3668
  }, ref) => {
3585
- console.log("system73Config", system73Config);
3586
3669
  const videoRef = useRef8(null);
3587
3670
  const containerRef = useRef8(null);
3671
+ const [isScriptsLoaded, setIsScriptsLoaded] = useState4(false);
3588
3672
  useImperativeHandle(ref, () => videoRef.current, []);
3589
3673
  const { playerRef, initializePlayer, destroyPlayer, isRetrying } = useShakaPlayer({
3590
3674
  src,
@@ -3635,7 +3719,8 @@ var Player = forwardRef(
3635
3719
  seekbarConfig,
3636
3720
  events?.onSkipBack,
3637
3721
  events?.onSkipForward,
3638
- iconSizes
3722
+ iconSizes,
3723
+ locale
3639
3724
  );
3640
3725
  const { isLive, isVisible: isLiveBadgeVisible } = useLiveBadge(playerRef, {
3641
3726
  enabled: true,
@@ -3675,7 +3760,11 @@ var Player = forwardRef(
3675
3760
  if (!imaConfig?.adTagUrl || !playerRef.current || !videoRef.current || !uiRef.current) {
3676
3761
  return;
3677
3762
  }
3678
- console.log("Initializing ads...");
3763
+ if (!window.google?.ima) {
3764
+ console.error("Google IMA SDK not available when trying to initialize ads");
3765
+ return;
3766
+ }
3767
+ console.log("Initializing ads with autoplay:", autoPlay);
3679
3768
  try {
3680
3769
  const player = playerRef.current;
3681
3770
  const video = videoRef.current;
@@ -3687,23 +3776,53 @@ var Player = forwardRef(
3687
3776
  console.error("Ad manager not available");
3688
3777
  return;
3689
3778
  }
3690
- adManager.initClientSide(container, video);
3691
3779
  const google = window.google;
3780
+ let adsRenderingSettings = null;
3781
+ if (imaConfig.adsRenderingSettings) {
3782
+ adsRenderingSettings = imaConfig.adsRenderingSettings;
3783
+ } else if (autoPlay) {
3784
+ adsRenderingSettings = new google.ima.AdsRenderingSettings();
3785
+ adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
3786
+ }
3787
+ adManager.initClientSide(container, video, adsRenderingSettings);
3692
3788
  const adsRequest = new google.ima.AdsRequest();
3693
3789
  adsRequest.adTagUrl = imaConfig.adTagUrl;
3694
3790
  adManager.requestClientSideAds(adsRequest);
3695
- console.log("Ads requested with tag:", imaConfig.adTagUrl);
3791
+ console.log("Ads requested successfully with tag:", imaConfig.adTagUrl, "autoplay:", autoPlay);
3696
3792
  } catch (error) {
3697
3793
  console.error("Error initializing ads:", error);
3698
3794
  }
3699
- }, [imaConfig]);
3795
+ }, [imaConfig, autoPlay]);
3796
+ useEffect5(() => {
3797
+ const loadRequiredScripts = async () => {
3798
+ try {
3799
+ const scriptLoaders = getRequiredScriptLoaders(!!imaConfig?.adTagUrl, !!system73Config?.apiKey);
3800
+ await loadScripts(scriptLoaders);
3801
+ const globalsToWait = [];
3802
+ if (imaConfig?.adTagUrl) {
3803
+ globalsToWait.push("google");
3804
+ }
3805
+ if (system73Config?.apiKey) {
3806
+ globalsToWait.push("S73ShakaPlayerWrapper");
3807
+ }
3808
+ if (globalsToWait.length > 0) {
3809
+ await waitForGlobals(globalsToWait);
3810
+ }
3811
+ setIsScriptsLoaded(true);
3812
+ } catch (error) {
3813
+ console.error("Error loading required scripts:", error);
3814
+ setIsScriptsLoaded(true);
3815
+ }
3816
+ };
3817
+ loadRequiredScripts();
3818
+ }, [imaConfig?.adTagUrl, system73Config?.apiKey]);
3700
3819
  useEffect5(() => {
3701
3820
  const video = videoRef.current;
3702
- if (!video) return;
3821
+ if (!video || !isScriptsLoaded) return;
3703
3822
  const initialize = async () => {
3704
3823
  try {
3705
3824
  let system73Wrapper = null;
3706
- if (system73Config?.apiKey) {
3825
+ if (system73Config?.apiKey && window.S73ShakaPlayerWrapper) {
3707
3826
  const playerConfig = { ...shakaConfig };
3708
3827
  system73Wrapper = initializeSystem73(playerConfig);
3709
3828
  if (system73Wrapper) {
@@ -3719,7 +3838,8 @@ var Player = forwardRef(
3719
3838
  const cleanupQuality = setupQualityTracking();
3720
3839
  configureQuality();
3721
3840
  await initializeUI();
3722
- if (imaConfig) {
3841
+ if (imaConfig?.adTagUrl && window.google?.ima) {
3842
+ console.log("Initializing ads immediately after UI setup");
3723
3843
  initializeAds();
3724
3844
  }
3725
3845
  } catch (error) {
@@ -3734,16 +3854,15 @@ var Player = forwardRef(
3734
3854
  destroyMux();
3735
3855
  destroyPlayer();
3736
3856
  };
3737
- }, [src]);
3857
+ }, [src, isScriptsLoaded]);
3738
3858
  useEffect5(() => {
3739
3859
  const video = videoRef.current;
3740
3860
  if (!video) return;
3741
3861
  video.autoplay = autoPlay;
3742
3862
  video.loop = loop;
3743
- video.muted = muted;
3744
3863
  video.controls = false;
3745
3864
  if (poster) video.poster = poster;
3746
- }, [autoPlay, loop, muted, poster]);
3865
+ }, [autoPlay, loop, muted, poster, imaConfig?.adTagUrl]);
3747
3866
  useEffect5(() => {
3748
3867
  const video = videoRef.current;
3749
3868
  if (!video) return;
@@ -3961,7 +4080,7 @@ var getErrorType = (error, video) => {
3961
4080
  };
3962
4081
 
3963
4082
  // src/messages/useMessages.tsx
3964
- import { useState as useState4, useEffect as useEffect6 } from "react";
4083
+ import { useState as useState5, useEffect as useEffect6 } from "react";
3965
4084
 
3966
4085
  // src/messages/en.json
3967
4086
  var en_default = {
@@ -4263,8 +4382,8 @@ var getBrowserLanguage = () => {
4263
4382
  return availableLanguages[language] ? language : "en";
4264
4383
  };
4265
4384
  var useMessages = (locale) => {
4266
- const [language, setLanguage] = useState4("en");
4267
- const [translations, setTranslations] = useState4(availableLanguages.en);
4385
+ const [language, setLanguage] = useState5("en");
4386
+ const [translations, setTranslations] = useState5(availableLanguages.en);
4268
4387
  useEffect6(() => {
4269
4388
  const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
4270
4389
  ;
@@ -4372,6 +4491,7 @@ var Video = ({
4372
4491
  src: activePlaylist,
4373
4492
  className: twMerge3("video-player-container", className),
4374
4493
  events,
4494
+ locale,
4375
4495
  containerClassName: "w-full h-full",
4376
4496
  children
4377
4497
  }
@@ -4379,7 +4499,7 @@ var Video = ({
4379
4499
  };
4380
4500
 
4381
4501
  // src/Event.tsx
4382
- import { useCallback as useCallback9, useEffect as useEffect8, useState as useState5 } from "react";
4502
+ import { useCallback as useCallback9, useEffect as useEffect8, useState as useState6 } from "react";
4383
4503
  import { twMerge as twMerge4 } from "tailwind-merge";
4384
4504
  import { useQuery as useQuery2 } from "@tanstack/react-query";
4385
4505
  import { Fragment, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
@@ -4412,8 +4532,8 @@ var Event = ({
4412
4532
  retry: queryOptions.retry ?? 3,
4413
4533
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
4414
4534
  });
4415
- const [activePlaylist, setActivePlaylist] = useState5();
4416
- const [activeVideoId, setActiveVideoId] = useState5();
4535
+ const [activePlaylist, setActivePlaylist] = useState6();
4536
+ const [activeVideoId, setActiveVideoId] = useState6();
4417
4537
  const videoIds = eventData?.videoIds ?? [];
4418
4538
  const {
4419
4539
  data: videosData,
@@ -4429,7 +4549,7 @@ var Event = ({
4429
4549
  retry: queryOptions.retry ?? 3,
4430
4550
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
4431
4551
  });
4432
- const [loadingApisState, setLoadingApisState] = useState5(true);
4552
+ const [loadingApisState, setLoadingApisState] = useState6(true);
4433
4553
  useEffect8(() => {
4434
4554
  if (videosData !== void 0) {
4435
4555
  setLoadingApisState(false);
@@ -4477,8 +4597,8 @@ var Event = ({
4477
4597
  }
4478
4598
  }
4479
4599
  }, [activeVideoId, videosData, events]);
4480
- const [error, setError] = useState5(null);
4481
- const [loadingPlaylist, setLoadingPlaylist] = useState5(true);
4600
+ const [error, setError] = useState6(null);
4601
+ const [loadingPlaylist, setLoadingPlaylist] = useState6(true);
4482
4602
  const videosDataError = videosData?.some((video) => !!video.error);
4483
4603
  useEffect8(() => {
4484
4604
  if (isEventLoading || videosIsLoading || loadingApisState) {
@@ -4540,6 +4660,7 @@ var Event = ({
4540
4660
  src: activePlaylist,
4541
4661
  className: twMerge4(className, "peer"),
4542
4662
  events,
4663
+ locale,
4543
4664
  containerClassName: "w-full h-full"
4544
4665
  }
4545
4666
  ) }),
@@ -4577,7 +4698,7 @@ function PreEvent({
4577
4698
  }) {
4578
4699
  const date = new Date(event.startTime);
4579
4700
  const now = /* @__PURE__ */ new Date();
4580
- const [remainingTime, setRemainingTime] = useState5(
4701
+ const [remainingTime, setRemainingTime] = useState6(
4581
4702
  date.getTime() - now.getTime()
4582
4703
  );
4583
4704
  const shouldBeStarted = remainingTime < 0;
@@ -4721,7 +4842,7 @@ var TitleAndDescription = ({
4721
4842
  };
4722
4843
 
4723
4844
  // src/CreativeWork.tsx
4724
- import { useEffect as useEffect9, useState as useState6 } from "react";
4845
+ import { useEffect as useEffect9, useState as useState7 } from "react";
4725
4846
  import { twMerge as twMerge5 } from "tailwind-merge";
4726
4847
  import { useQuery as useQuery3 } from "@tanstack/react-query";
4727
4848
  import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
@@ -4754,9 +4875,9 @@ var CreativeWork = ({
4754
4875
  retry: queryOptions.retry ?? 3,
4755
4876
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
4756
4877
  });
4757
- const [activePlaylist, setActivePlaylist] = useState6();
4758
- const [activeVideoId, setActiveVideoId] = useState6();
4759
- const [showCountDown, setShowCountDown] = useState6(false);
4878
+ const [activePlaylist, setActivePlaylist] = useState7();
4879
+ const [activeVideoId, setActiveVideoId] = useState7();
4880
+ const [showCountDown, setShowCountDown] = useState7(false);
4760
4881
  const videoIds = creativeWorkData?.videoIds ?? [];
4761
4882
  const {
4762
4883
  data: videosData,
@@ -4772,7 +4893,7 @@ var CreativeWork = ({
4772
4893
  retry: queryOptions.retry ?? 3,
4773
4894
  retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
4774
4895
  });
4775
- const [loadingApisState, setLoadingApisState] = useState6(true);
4896
+ const [loadingApisState, setLoadingApisState] = useState7(true);
4776
4897
  useEffect9(() => {
4777
4898
  if (videosData !== void 0) {
4778
4899
  setLoadingApisState(false);
@@ -4823,7 +4944,7 @@ var CreativeWork = ({
4823
4944
  }
4824
4945
  }
4825
4946
  }, [activeVideoId, videosData, events]);
4826
- const [error, setError] = useState6(null);
4947
+ const [error, setError] = useState7(null);
4827
4948
  const videosDataError = videosData?.some((video) => !!video.error);
4828
4949
  useEffect9(() => {
4829
4950
  if (creativeWorkError || videosError || videosDataError) {
@@ -4847,7 +4968,7 @@ var CreativeWork = ({
4847
4968
  }
4848
4969
  ) }) });
4849
4970
  }
4850
- const [loadingPlaylist, setLoadingPlaylist] = useState6(true);
4971
+ const [loadingPlaylist, setLoadingPlaylist] = useState7(true);
4851
4972
  useEffect9(() => {
4852
4973
  const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
4853
4974
  const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
@@ -4895,6 +5016,7 @@ var CreativeWork = ({
4895
5016
  ...events
4896
5017
  },
4897
5018
  src: activePlaylist,
5019
+ locale,
4898
5020
  containerClassName: "w-full h-full"
4899
5021
  }
4900
5022
  ),
@@ -4924,7 +5046,7 @@ function PreCreativeWork({
4924
5046
  }) {
4925
5047
  const date = new Date(creativeWork.releaseTime);
4926
5048
  const now = /* @__PURE__ */ new Date();
4927
- const [remainingTime, setRemainingTime] = useState6(
5049
+ const [remainingTime, setRemainingTime] = useState7(
4928
5050
  date.getTime() - now.getTime()
4929
5051
  );
4930
5052
  const shouldBeStarted = remainingTime < 0;