@mottosports/motto-video-player 1.0.1-rc.31 → 1.0.1-rc.33

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
@@ -374,6 +374,9 @@ styleInject(`/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */
374
374
  .grid {
375
375
  display: grid;
376
376
  }
377
+ .hidden {
378
+ display: none;
379
+ }
377
380
  .aspect-video {
378
381
  aspect-ratio: var(--aspect-video);
379
382
  }
@@ -1103,7 +1106,7 @@ styleInject(`/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */
1103
1106
  `);
1104
1107
 
1105
1108
  // src/Player.tsx
1106
- import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle } from "react";
1109
+ import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle, useMemo } from "react";
1107
1110
  import shaka3 from "shaka-player/dist/shaka-player.ui";
1108
1111
 
1109
1112
  // src/hooks/useShakePlayer.ts
@@ -1137,7 +1140,7 @@ var isPlayReadySupported = () => {
1137
1140
  import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
1138
1141
 
1139
1142
  // package.json
1140
- var version = "1.0.1-rc.31";
1143
+ var version = "1.0.1-rc.33";
1141
1144
 
1142
1145
  // src/hooks/useShakePlayer.ts
1143
1146
  var useShakePlayer = ({
@@ -1151,33 +1154,57 @@ var useShakePlayer = ({
1151
1154
  onMuxDataUpdate
1152
1155
  }) => {
1153
1156
  const playerRef = useRef(null);
1157
+ const isDestroyingRef = useRef(false);
1154
1158
  const initializePlayer = useCallback(async (video) => {
1159
+ console.log("\u{1F3AC} PLAYER-INIT: Starting player initialization...");
1160
+ const startTime = performance.now();
1155
1161
  try {
1162
+ console.log("\u{1F3AC} PLAYER-INIT: Installing polyfills...");
1156
1163
  shaka.polyfill.installAll();
1164
+ console.log("\u{1F3AC} PLAYER-INIT: Polyfills installed successfully");
1165
+ console.log("\u{1F3AC} PLAYER-INIT: Checking browser support...");
1157
1166
  if (!shaka.Player.isBrowserSupported()) {
1167
+ console.error("\u{1F3AC} PLAYER-INIT: Browser not supported by Shaka Player");
1158
1168
  throw new Error("Browser not supported by Shaka Player");
1159
1169
  }
1170
+ console.log("\u{1F3AC} PLAYER-INIT: Browser support confirmed");
1171
+ console.log("\u{1F3AC} PLAYER-INIT: Creating player instance...");
1160
1172
  const player = new shaka.Player();
1161
1173
  playerRef.current = player;
1174
+ console.log("\u{1F3AC} PLAYER-INIT: Player instance created successfully");
1175
+ console.log("\u{1F3AC} PLAYER-INIT: Attaching player to video element...");
1162
1176
  await player.attach(video);
1177
+ console.log("\u{1F3AC} PLAYER-INIT: Player attached to video element successfully");
1178
+ console.log("\u{1F3AC} PLAYER-INIT: Configuring player...");
1163
1179
  if (shakaConfig) {
1180
+ console.log("\u{1F3AC} PLAYER-INIT: Applying custom shaka config:", shakaConfig);
1164
1181
  player.configure(shakaConfig);
1182
+ console.log("\u{1F3AC} PLAYER-INIT: Custom shaka config applied");
1183
+ } else {
1184
+ console.log("\u{1F3AC} PLAYER-INIT: No custom shaka config provided");
1165
1185
  }
1166
1186
  let manifestUrl = src.url;
1167
1187
  const isDRM = Boolean(src.drm);
1168
1188
  let cert = null;
1169
1189
  if (isDRM) {
1190
+ console.log("\u{1F3AC} PLAYER-INIT: DRM detected, setting up DRM configuration...");
1170
1191
  const isPlayReady = isPlayReadySupported();
1192
+ console.log("\u{1F3AC} PLAYER-INIT: Device capabilities - Apple:", isAppleDevice(), "PlayReady:", isPlayReady);
1171
1193
  if (isAppleDevice() && src.drm.fairplay?.certificate_url) {
1194
+ console.log("\u{1F3AC} PLAYER-INIT: Setting up FairPlay DRM...");
1172
1195
  const req = await fetch(src.drm.fairplay.certificate_url);
1173
1196
  cert = await req.arrayBuffer();
1174
1197
  manifestUrl = src.drm.fairplay.playlist_url;
1198
+ console.log("\u{1F3AC} PLAYER-INIT: FairPlay certificate loaded");
1175
1199
  } else if (isPlayReady && src.drm.playready?.license_url) {
1200
+ console.log("\u{1F3AC} PLAYER-INIT: Setting up PlayReady DRM...");
1176
1201
  manifestUrl = src.drm.playready.playlist_url;
1177
1202
  } else {
1203
+ console.log("\u{1F3AC} PLAYER-INIT: Setting up Widevine DRM...");
1178
1204
  manifestUrl = src.drm?.widevine?.playlist_url || "";
1179
1205
  }
1180
- player.configure({
1206
+ console.log("\u{1F3AC} PLAYER-INIT: Configuring DRM servers...");
1207
+ const drmConfig2 = {
1181
1208
  drm: {
1182
1209
  servers: {
1183
1210
  "com.widevine.alpha": src.drm.widevine?.license_url,
@@ -1192,34 +1219,52 @@ var useShakePlayer = ({
1192
1219
  }
1193
1220
  }
1194
1221
  }
1195
- });
1222
+ };
1223
+ console.log("\u{1F3AC} PLAYER-INIT: DRM config:", drmConfig2);
1224
+ player.configure(drmConfig2);
1225
+ console.log("\u{1F3AC} PLAYER-INIT: DRM configuration applied");
1226
+ console.log("\u{1F3AC} PLAYER-INIT: Setting up DRM network filters...");
1196
1227
  const netEngine = player.getNetworkingEngine();
1197
1228
  if (netEngine) {
1229
+ console.log("\u{1F3AC} PLAYER-INIT: Registering DRM request filter...");
1198
1230
  netEngine.registerRequestFilter((type, request) => {
1199
1231
  if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
1232
+ console.log("\u{1F3AC} PLAYER-INIT: Adding DRM token to license request");
1200
1233
  request.headers["x-dt-custom-data"] = src.drm.token;
1201
1234
  }
1202
1235
  });
1236
+ console.log("\u{1F3AC} PLAYER-INIT: Registering DRM response filter...");
1203
1237
  netEngine.registerResponseFilter((type, response) => {
1204
1238
  if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
1205
1239
  const ks = player.keySystem && player.keySystem();
1206
1240
  if (ks === "com.apple.fps") {
1241
+ console.log("\u{1F3AC} PLAYER-INIT: Processing FairPlay license response");
1207
1242
  const responseText = shaka.util.StringUtils.fromUTF8(response.data);
1208
1243
  response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
1209
1244
  }
1210
1245
  }
1211
1246
  });
1247
+ console.log("\u{1F3AC} PLAYER-INIT: DRM network filters registered");
1248
+ } else {
1249
+ console.warn("\u{1F3AC} PLAYER-INIT: No networking engine available for DRM filters");
1212
1250
  }
1251
+ } else {
1252
+ console.log("\u{1F3AC} PLAYER-INIT: No DRM configuration needed");
1213
1253
  }
1254
+ console.log("\u{1F3AC} PLAYER-INIT: Setting up error handling...");
1214
1255
  player?.addEventListener("error", (event) => {
1215
1256
  const error = event.detail;
1216
1257
  if (error?.code === 7e3) {
1258
+ console.log("\u{1F3AC} PLAYER-INIT: Ignoring benign LOAD_INTERRUPTED error (7000)");
1217
1259
  return;
1218
1260
  }
1219
- console.error("Shaka Player Error:", error);
1261
+ console.error("\u{1F3AC} PLAYER-INIT: Shaka Player Error:", error);
1220
1262
  onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
1221
1263
  });
1264
+ console.log("\u{1F3AC} PLAYER-INIT: Error handling configured");
1265
+ console.log("\u{1F3AC} PLAYER-INIT: Checking Mux configuration...");
1222
1266
  if (muxConfig) {
1267
+ console.log("\u{1F3AC} PLAYER-INIT: Initializing Mux Analytics...");
1223
1268
  try {
1224
1269
  const playerInitTime = initShakaPlayerMux.utils.now();
1225
1270
  const muxOptions = {
@@ -1240,33 +1285,54 @@ var useShakePlayer = ({
1240
1285
  ...muxConfig.metadata
1241
1286
  }
1242
1287
  };
1288
+ console.log("\u{1F3AC} PLAYER-INIT: Mux options:", muxOptions);
1243
1289
  initShakaPlayerMux(player, muxOptions, shaka);
1290
+ console.log("\u{1F3AC} PLAYER-INIT: Mux Analytics initialized successfully");
1244
1291
  onMuxReady?.();
1245
1292
  } catch (error) {
1246
- console.error("Failed to initialize Mux Analytics:", error);
1293
+ console.error("\u{1F3AC} PLAYER-INIT: Failed to initialize Mux Analytics:", error);
1247
1294
  }
1295
+ } else {
1296
+ console.log("\u{1F3AC} PLAYER-INIT: No Mux configuration provided");
1248
1297
  }
1298
+ console.log("\u{1F3AC} PLAYER-INIT: Loading manifest:", manifestUrl);
1299
+ console.log("\u{1F3AC} PLAYER-INIT: CRITICAL - Using manifestUrl instead of hardcoded URL");
1249
1300
  await player.load(manifestUrl);
1301
+ console.log("\u{1F3AC} PLAYER-INIT: Manifest loaded successfully");
1302
+ const endTime = performance.now();
1303
+ console.log(`\u{1F3AC} PLAYER-INIT: Player initialization completed in ${(endTime - startTime).toFixed(2)}ms`);
1250
1304
  onPlayerReady?.(player);
1251
1305
  return player;
1252
1306
  } catch (error) {
1253
1307
  if (error?.code === 7e3) {
1308
+ console.log("\u{1F3AC} PLAYER-INIT: Caught benign LOAD_INTERRUPTED error during initialization");
1254
1309
  return;
1255
1310
  }
1256
- console.error("Error initializing Shaka Player:", error);
1311
+ const endTime = performance.now();
1312
+ console.error(`\u{1F3AC} PLAYER-INIT: Error during initialization after ${(endTime - startTime).toFixed(2)}ms:`, error);
1257
1313
  onError?.(error);
1258
1314
  throw error;
1259
1315
  }
1260
1316
  }, [shakaConfig, drmConfig, src, onError, onPlayerReady, muxConfig, onMuxReady]);
1261
1317
  const destroyPlayer = useCallback(async () => {
1262
- if (playerRef.current) {
1318
+ if (playerRef.current && !isDestroyingRef.current) {
1319
+ isDestroyingRef.current = true;
1320
+ console.log("\u{1F3AC} PLAYER-DESTROY: Setting destroy flag to prevent race conditions");
1263
1321
  try {
1322
+ console.log("\u{1F3AC} PLAYER-DESTROY: Destroying player instance...");
1264
1323
  await playerRef.current.destroy();
1324
+ console.log("\u{1F3AC} PLAYER-DESTROY: Player instance destroyed successfully");
1265
1325
  } catch (error) {
1266
- console.warn("Error destroying Shaka Player:", error);
1326
+ console.warn("\u{1F3AC} PLAYER-DESTROY: Error destroying Shaka Player:", error);
1267
1327
  } finally {
1268
1328
  playerRef.current = null;
1329
+ isDestroyingRef.current = false;
1330
+ console.log("\u{1F3AC} PLAYER-DESTROY: Player reference cleared and destroy flag reset");
1269
1331
  }
1332
+ } else if (isDestroyingRef.current) {
1333
+ console.log("\u{1F3AC} PLAYER-DESTROY: Destroy already in progress, skipping...");
1334
+ } else {
1335
+ console.log("\u{1F3AC} PLAYER-DESTROY: No player instance to destroy");
1270
1336
  }
1271
1337
  }, [playerRef]);
1272
1338
  return {
@@ -1684,20 +1750,198 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1684
1750
  const uiRef = useRef4(null);
1685
1751
  const registeredElements = useRef4(/* @__PURE__ */ new Set());
1686
1752
  const initializeUI = useCallback5(async () => {
1687
- if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
1753
+ console.log("\u{1F3AE} UI-INIT: Starting Shaka UI initialization...");
1754
+ const startTime = performance.now();
1755
+ if (!controls) {
1756
+ console.log("\u{1F3AE} UI-INIT: Controls disabled, skipping UI initialization");
1757
+ return null;
1758
+ }
1759
+ if (!containerRef.current) {
1760
+ console.warn("\u{1F3AE} UI-INIT: Container ref not available, skipping UI initialization");
1761
+ return null;
1762
+ }
1763
+ if (!playerRef.current) {
1764
+ console.warn("\u{1F3AE} UI-INIT: Player ref not available, skipping UI initialization");
1765
+ console.warn("\u{1F3AE} UI-INIT: This might be due to a race condition - player destroyed before UI init");
1766
+ console.log("\u{1F3AE} UI-INIT: Attempting to wait for player reference...");
1767
+ let waitAttempts = 0;
1768
+ const maxWaitAttempts = 10;
1769
+ while (!playerRef.current && waitAttempts < maxWaitAttempts) {
1770
+ await new Promise((resolve) => setTimeout(resolve, 100));
1771
+ waitAttempts++;
1772
+ console.log(`\u{1F3AE} UI-INIT: Waiting for player ref... attempt ${waitAttempts}`);
1773
+ }
1774
+ if (!playerRef.current) {
1775
+ console.error("\u{1F3AE} UI-INIT: Player ref still not available after waiting, aborting UI initialization");
1776
+ return null;
1777
+ } else {
1778
+ console.log(`\u{1F3AE} UI-INIT: Player ref became available after ${waitAttempts * 100}ms`);
1779
+ }
1780
+ }
1781
+ const player = playerRef.current;
1782
+ console.log("\u{1F3AE} UI-INIT: RACE CHECK - Player state analysis:");
1783
+ console.log("\u{1F3AE} UI-INIT: - Player exists:", !!player);
1784
+ if (!player) {
1785
+ console.error("\u{1F3AE} UI-INIT: CRITICAL - Player reference is null during UI initialization!");
1786
+ console.error("\u{1F3AE} UI-INIT: This indicates a race condition between player destruction and UI initialization");
1787
+ return null;
1788
+ }
1789
+ console.log("\u{1F3AE} UI-INIT: - Player isDestroyed:", player.isDestroyed && player.isDestroyed());
1790
+ console.log("\u{1F3AE} UI-INIT: - Player getNetworkingEngine:", !!player.getNetworkingEngine());
1791
+ console.log("\u{1F3AE} UI-INIT: - Player getConfiguration:", !!player.getConfiguration);
1792
+ try {
1793
+ const config = player.getConfiguration();
1794
+ console.log("\u{1F3AE} UI-INIT: - Player configuration available:", !!config);
1795
+ if (player.isDestroyed && player.isDestroyed()) {
1796
+ console.error("\u{1F3AE} UI-INIT: CRITICAL - Player is destroyed, aborting UI initialization");
1797
+ return null;
1798
+ }
1799
+ } catch (error) {
1800
+ console.warn("\u{1F3AE} UI-INIT: - WARNING: Could not get player configuration:", error);
1801
+ console.warn("\u{1F3AE} UI-INIT: - This may indicate the player is in an invalid state");
1802
+ return null;
1803
+ }
1804
+ if (!videoRef.current) {
1805
+ console.warn("\u{1F3AE} UI-INIT: Video ref not available, skipping UI initialization");
1688
1806
  return null;
1689
1807
  }
1808
+ console.log("\u{1F3AE} UI-INIT: All prerequisites met, proceeding with initialization");
1809
+ const chromecastAPICheck = {
1810
+ chromeExists: !!window.chrome,
1811
+ castExists: !!window.chrome?.cast,
1812
+ isAvailable: !!window.chrome?.cast?.isAvailable,
1813
+ sessionExists: !!window.chrome?.cast?.Session,
1814
+ receiverExists: !!window.chrome?.cast?.ReceiverAvailability
1815
+ };
1816
+ console.log("\u{1F3AE} UI-INIT: CRITICAL - Chromecast API state before UI init:", chromecastAPICheck);
1817
+ if (chromecastConfig) {
1818
+ try {
1819
+ console.log("\u{1F3AE} CAST-DIAG: Secure context:", window.isSecureContext, "Protocol:", window.location.protocol);
1820
+ console.log("\u{1F3AE} CAST-DIAG: UserAgent:", navigator.userAgent);
1821
+ console.log("\u{1F3AE} CAST-DIAG: In iframe:", window.top !== window.self);
1822
+ const existingCastScript = document.querySelector('script#gcast_sender, script[src*="cast_sender.js"]');
1823
+ if (existingCastScript) {
1824
+ console.log("\u{1F3AE} CAST-DIAG: Found existing cast sender script:", {
1825
+ id: existingCastScript.id,
1826
+ src: existingCastScript.src,
1827
+ async: existingCastScript.async,
1828
+ defer: existingCastScript.defer,
1829
+ dataset: existingCastScript.dataset
1830
+ });
1831
+ } else {
1832
+ console.log("\u{1F3AE} CAST-DIAG: No cast sender script present yet");
1833
+ }
1834
+ } catch (e) {
1835
+ console.warn("\u{1F3AE} CAST-DIAG: Environment diagnostics failed", e);
1836
+ }
1837
+ const hasCastFramework = !!window.chrome?.cast?.framework?.CastContext;
1838
+ if (!hasCastFramework) {
1839
+ console.warn("\u{1F3AE} UI-INIT: Cast Framework not loaded. Attempting to load sender library...");
1840
+ const loadCastFramework = () => new Promise((resolve) => {
1841
+ if (window.chrome?.cast?.framework?.CastContext) {
1842
+ return resolve();
1843
+ }
1844
+ if (!document.getElementById("gcast_sender")) {
1845
+ const script = document.createElement("script");
1846
+ script.id = "gcast_sender";
1847
+ script.src = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1";
1848
+ script.async = true;
1849
+ script.defer = true;
1850
+ script.addEventListener("load", () => {
1851
+ console.log("\u{1F3AE} CAST-LOAD: cast_sender.js loaded");
1852
+ });
1853
+ script.addEventListener("error", (err) => {
1854
+ console.error("\u{1F3AE} CAST-LOAD: cast_sender.js failed to load", err);
1855
+ });
1856
+ document.head.appendChild(script);
1857
+ console.log("\u{1F3AE} CAST-LOAD: Injected cast sender script tag");
1858
+ }
1859
+ const previousCallback = window.__onGCastApiAvailable;
1860
+ window.__onGCastApiAvailable = (isAvailable) => {
1861
+ console.log("\u{1F3AE} UI-INIT: __onGCastApiAvailable called. Available:", isAvailable);
1862
+ try {
1863
+ console.log("\u{1F3AE} CAST-CB: chrome.cast exists:", !!window.chrome?.cast);
1864
+ console.log("\u{1F3AE} CAST-CB: chrome.cast.isAvailable:", !!window.chrome?.cast?.isAvailable);
1865
+ console.log("\u{1F3AE} CAST-CB: chrome.cast.framework exists:", !!window.chrome?.cast?.framework);
1866
+ console.log("\u{1F3AE} CAST-CB: CastContext exists:", !!window.chrome?.cast?.framework?.CastContext);
1867
+ } catch (e) {
1868
+ console.warn("\u{1F3AE} CAST-CB: Diagnostics failed", e);
1869
+ }
1870
+ if (typeof previousCallback === "function") {
1871
+ try {
1872
+ previousCallback(isAvailable);
1873
+ } catch {
1874
+ }
1875
+ }
1876
+ resolve();
1877
+ };
1878
+ let attempts = 0;
1879
+ const maxAttempts = 50;
1880
+ const poll = setInterval(() => {
1881
+ attempts++;
1882
+ const hasCast = !!window.chrome?.cast;
1883
+ const hasFramework = !!window.chrome?.cast?.framework;
1884
+ const hasContext = !!window.chrome?.cast?.framework?.CastContext;
1885
+ if (attempts % 10 === 0) {
1886
+ console.log(`\u{1F3AE} CAST-POLL: attempt=${attempts} cast=${hasCast} framework=${hasFramework} context=${hasContext}`);
1887
+ }
1888
+ if (hasContext || attempts >= maxAttempts) {
1889
+ clearInterval(poll);
1890
+ resolve();
1891
+ }
1892
+ }, 100);
1893
+ });
1894
+ await loadCastFramework();
1895
+ console.log("\u{1F3AE} UI-INIT: Cast Framework load attempt complete. Framework present:", !!window.chrome?.cast?.framework?.CastContext);
1896
+ if (!window.chrome?.cast?.framework?.CastContext) {
1897
+ console.warn("\u{1F3AE} UI-INIT: CastContext still missing after load. Potential causes:");
1898
+ console.warn("\u{1F3AE} UI-INIT: - Script blocked by CSP/adblock");
1899
+ console.warn("\u{1F3AE} UI-INIT: - Non-secure origin (requires https/localhost)");
1900
+ console.warn("\u{1F3AE} UI-INIT: - Non-Chrome browser or incognito restrictions");
1901
+ }
1902
+ }
1903
+ }
1904
+ if (chromecastConfig && !chromecastAPICheck.castExists) {
1905
+ console.warn("\u{1F3AE} UI-INIT: WARNING - Chromecast config provided but Cast API not available!");
1906
+ console.warn("\u{1F3AE} UI-INIT: This could cause race condition issues");
1907
+ console.log("\u{1F3AE} UI-INIT: Waiting for Cast API to be available...");
1908
+ let waitAttempts = 0;
1909
+ const maxWaitAttempts = 50;
1910
+ while (!window.chrome?.cast?.isAvailable && waitAttempts < maxWaitAttempts) {
1911
+ await new Promise((resolve) => setTimeout(resolve, 100));
1912
+ waitAttempts++;
1913
+ if (waitAttempts % 10 === 0) {
1914
+ console.log(`\u{1F3AE} UI-INIT: Still waiting for Cast API... (${waitAttempts * 100}ms)`);
1915
+ }
1916
+ }
1917
+ if (window.chrome?.cast?.isAvailable) {
1918
+ console.log(`\u{1F3AE} UI-INIT: Cast API became available after ${waitAttempts * 100}ms`);
1919
+ } else {
1920
+ console.warn(`\u{1F3AE} UI-INIT: Cast API not available after ${waitAttempts * 100}ms, proceeding anyway`);
1921
+ }
1922
+ }
1923
+ console.log("\u{1F3AE} UI-INIT: Registering custom UI elements...");
1690
1924
  if (!registeredElements.current.has("skip_back_button")) {
1925
+ console.log("\u{1F3AE} UI-INIT: Registering skip_back_button element");
1691
1926
  ShakaUI.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack, iconSizes?.skipButtons));
1692
1927
  registeredElements.current.add("skip_back_button");
1928
+ } else {
1929
+ console.log("\u{1F3AE} UI-INIT: skip_back_button already registered");
1693
1930
  }
1694
1931
  if (!registeredElements.current.has("skip_forward_button")) {
1932
+ console.log("\u{1F3AE} UI-INIT: Registering skip_forward_button element");
1695
1933
  ShakaUI.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward, iconSizes?.skipButtons));
1696
1934
  registeredElements.current.add("skip_forward_button");
1935
+ } else {
1936
+ console.log("\u{1F3AE} UI-INIT: skip_forward_button already registered");
1697
1937
  }
1938
+ console.log("\u{1F3AE} UI-INIT: Creating Shaka UI Overlay...");
1698
1939
  const ui = new ShakaUI.Overlay(playerRef.current, containerRef.current, videoRef.current);
1699
1940
  uiRef.current = ui;
1941
+ console.log("\u{1F3AE} UI-INIT: Shaka UI Overlay created successfully");
1700
1942
  const isMobile = window.innerWidth <= 767;
1943
+ console.log("\u{1F3AE} UI-INIT: Device detection - Mobile:", isMobile, "Width:", window.innerWidth);
1944
+ console.log("\u{1F3AE} UI-INIT: Building control panel elements...");
1701
1945
  const controlPanelElements = [
1702
1946
  ...isMobile ? [] : ["skip_back_button"],
1703
1947
  ...isMobile ? [] : ["play_pause"],
@@ -1709,8 +1953,14 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1709
1953
  "spacer",
1710
1954
  "fullscreen",
1711
1955
  "cast",
1956
+ // Always show cast button
1712
1957
  "overflow_menu"
1713
1958
  ];
1959
+ console.log("\u{1F3AE} UI-INIT: Control panel elements:", controlPanelElements);
1960
+ console.log("\u{1F3AE} UI-INIT: Configuring Chromecast settings...");
1961
+ const castReceiverAppId = chromecastConfig?.receiverApplicationId || "CC1AD845";
1962
+ console.log("\u{1F3AE} UI-INIT: Cast receiver app ID:", castReceiverAppId);
1963
+ console.log("\u{1F3AE} UI-INIT: Chromecast config provided:", !!chromecastConfig, chromecastConfig);
1714
1964
  const uiConfig = {
1715
1965
  seekBarColors: {
1716
1966
  base: seekbarColors?.base || "rgba(255, 255, 255, 0.3)",
@@ -1722,25 +1972,76 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1722
1972
  },
1723
1973
  controlPanelElements,
1724
1974
  addBigPlayButton: isMobile,
1725
- ...chromecastConfig?.receiverApplicationId && {
1726
- "castReceiverAppId": chromecastConfig.receiverApplicationId,
1727
- "castAndroidReceiverCompatible": false
1728
- },
1975
+ // Always configure chromecast with defaults or provided config
1976
+ castReceiverAppId,
1977
+ castAndroidReceiverCompatible: true,
1978
+ // Enable Android TV compatibility
1729
1979
  overflowMenuButtons: [
1730
1980
  "quality",
1731
1981
  "picture_in_picture",
1732
1982
  "playback_rate"
1733
1983
  ]
1734
1984
  };
1735
- if (chromecastConfig?.receiverApplicationId) {
1736
- uiConfig.castReceiverAppId = chromecastConfig.receiverApplicationId;
1737
- uiConfig.castAndroidReceiverCompatible = false;
1985
+ console.log("\u{1F3AE} UI-INIT: Final UI config:", uiConfig);
1986
+ console.log("\u{1F3AE} UI-INIT: Applying UI configuration...");
1987
+ console.log("\u{1F3AE} UI-INIT: RACE CHECK - Pre-configure state:");
1988
+ console.log("\u{1F3AE} UI-INIT: - UI exists:", !!ui);
1989
+ console.log("\u{1F3AE} UI-INIT: - Cast receiver ID:", uiConfig.castReceiverAppId);
1990
+ console.log("\u{1F3AE} UI-INIT: - Cast compatibility:", uiConfig.castAndroidReceiverCompatible);
1991
+ const configureStartTime = performance.now();
1992
+ try {
1993
+ ui.configure(uiConfig);
1994
+ const configureEndTime = performance.now();
1995
+ console.log(`\u{1F3AE} UI-INIT: UI configuration applied successfully in ${(configureEndTime - configureStartTime).toFixed(2)}ms`);
1996
+ setTimeout(() => {
1997
+ const castButton = containerRef.current?.querySelector(".shaka-cast-button");
1998
+ const castAvailable = !!window.chrome?.cast?.isAvailable;
1999
+ console.log("\u{1F3AE} UI-INIT: POST-CONFIGURE CAST CHECK:");
2000
+ console.log("\u{1F3AE} UI-INIT: - Cast button found:", !!castButton);
2001
+ console.log("\u{1F3AE} UI-INIT: - Chrome cast API available:", castAvailable);
2002
+ console.log("\u{1F3AE} UI-INIT: - Cast button visible:", castButton ? !castButton.hasAttribute("hidden") : false);
2003
+ if (castButton) {
2004
+ castButton.addEventListener("click", async () => {
2005
+ console.log("\u{1F3AE} CAST-CLICK: Cast button clicked!");
2006
+ console.log("\u{1F3AE} CAST-CLICK: Player state:", {
2007
+ exists: !!playerRef.current,
2008
+ isDestroyed: playerRef.current?.isDestroyed?.(),
2009
+ videoLoaded: !!videoRef.current?.src,
2010
+ videoCurrentTime: videoRef.current?.currentTime,
2011
+ videoDuration: videoRef.current?.duration
2012
+ });
2013
+ const cast = window.chrome?.cast;
2014
+ const framework = cast?.framework;
2015
+ if (framework?.CastContext) {
2016
+ const castContext = framework.CastContext.getInstance();
2017
+ try {
2018
+ castContext.setOptions?.({
2019
+ receiverApplicationId: chromecastConfig?.receiverApplicationId || "CC1AD845",
2020
+ autoJoinPolicy: cast?.AutoJoinPolicy?.TAB_AND_ORIGIN_SCOPED || "origin_scoped"
2021
+ });
2022
+ console.log("\u{1F3AE} CAST-CLICK: CastContext options set");
2023
+ } catch (e) {
2024
+ console.warn("\u{1F3AE} CAST-CLICK: Failed to set CastContext options", e);
2025
+ }
2026
+ console.log("\u{1F3AE} CAST-CLICK: Cast state:", castContext.getCastState?.());
2027
+ } else {
2028
+ console.warn("\u{1F3AE} CAST-CLICK: Cast framework not available on click");
2029
+ }
2030
+ });
2031
+ }
2032
+ }, 50);
2033
+ } catch (error) {
2034
+ const configureEndTime = performance.now();
2035
+ console.error(`\u{1F3AE} UI-INIT: ERROR during UI configuration after ${(configureEndTime - configureStartTime).toFixed(2)}ms:`, error);
2036
+ throw error;
1738
2037
  }
1739
- ui.configure(uiConfig);
2038
+ console.log("\u{1F3AE} UI-INIT: Setting up mobile-specific customizations...");
1740
2039
  if (isMobile) {
2040
+ console.log("\u{1F3AE} UI-INIT: Setting up big play button customization for mobile");
1741
2041
  const customizeBigPlayButton = () => {
1742
2042
  const bigPlayButton = containerRef.current?.querySelector(".shaka-big-play-button");
1743
2043
  if (bigPlayButton && !bigPlayButton.hasAttribute("data-customized")) {
2044
+ console.log("\u{1F3AE} UI-INIT: Customizing big play button");
1744
2045
  const buttonSize = iconSizes?.bigPlayButton || 40;
1745
2046
  bigPlayButton.innerHTML = renderIcon(BigPlayIcon, { size: buttonSize });
1746
2047
  bigPlayButton.setAttribute("data-customized", "true");
@@ -1748,8 +2049,10 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1748
2049
  buttonElement.style.display = "flex";
1749
2050
  buttonElement.style.alignItems = "center";
1750
2051
  buttonElement.style.justifyContent = "center";
2052
+ console.log("\u{1F3AE} UI-INIT: Big play button customized successfully");
1751
2053
  }
1752
2054
  };
2055
+ console.log("\u{1F3AE} UI-INIT: Scheduling big play button customization");
1753
2056
  setTimeout(customizeBigPlayButton, 100);
1754
2057
  const observer = new MutationObserver(() => {
1755
2058
  customizeBigPlayButton();
@@ -1760,18 +2063,29 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1760
2063
  subtree: true,
1761
2064
  attributes: false
1762
2065
  });
2066
+ console.log("\u{1F3AE} UI-INIT: Mutation observer set up for big play button");
1763
2067
  }
2068
+ } else {
2069
+ console.log("\u{1F3AE} UI-INIT: Desktop mode - skipping big play button customization");
1764
2070
  }
2071
+ console.log("\u{1F3AE} UI-INIT: Seekbar styling handled by CSS");
2072
+ const endTime = performance.now();
2073
+ console.log(`\u{1F3AE} UI-INIT: UI initialization completed successfully in ${(endTime - startTime).toFixed(2)}ms`);
1765
2074
  return ui;
1766
2075
  }, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes]);
1767
2076
  const destroyUI = useCallback5(() => {
1768
2077
  if (uiRef.current) {
1769
2078
  try {
2079
+ console.log("\u{1F3AE} UI-DESTROY: Destroying Shaka UI...");
1770
2080
  uiRef.current.destroy();
2081
+ console.log("\u{1F3AE} UI-DESTROY: Shaka UI destroyed successfully");
1771
2082
  } catch (error) {
1772
- console.error("Error destroying UI:", error);
2083
+ console.error("\u{1F3AE} UI-DESTROY: Error destroying UI:", error);
1773
2084
  }
1774
2085
  uiRef.current = null;
2086
+ console.log("\u{1F3AE} UI-DESTROY: UI reference cleared");
2087
+ } else {
2088
+ console.log("\u{1F3AE} UI-DESTROY: No UI instance to destroy");
1775
2089
  }
1776
2090
  }, []);
1777
2091
  return {
@@ -2538,6 +2852,9 @@ styleInject(`/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */
2538
2852
  .grid {
2539
2853
  display: grid;
2540
2854
  }
2855
+ .hidden {
2856
+ display: none;
2857
+ }
2541
2858
  .aspect-video {
2542
2859
  aspect-ratio: var(--aspect-video);
2543
2860
  }
@@ -3295,14 +3612,18 @@ var Player = forwardRef(
3295
3612
  const videoRef = useRef8(null);
3296
3613
  const containerRef = useRef8(null);
3297
3614
  const adContainerRef = useRef8(null);
3615
+ const isInitializingRef = useRef8(false);
3616
+ const stableShakaConfig = useMemo(() => shakaConfig, [shakaConfig]);
3617
+ const stableDrmConfig = useMemo(() => drmConfig, [drmConfig]);
3618
+ const stableMuxConfig = useMemo(() => muxConfig, [muxConfig]);
3298
3619
  useImperativeHandle(ref, () => videoRef.current, []);
3299
3620
  const { playerRef, initializePlayer, destroyPlayer } = useShakePlayer({
3300
3621
  src,
3301
- shakaConfig,
3302
- drmConfig,
3622
+ shakaConfig: stableShakaConfig,
3623
+ drmConfig: stableDrmConfig,
3303
3624
  onError: events?.onError,
3304
3625
  onPlayerReady: events?.onPlayerReady,
3305
- muxConfig,
3626
+ muxConfig: stableMuxConfig,
3306
3627
  onMuxReady: events?.onMuxReady,
3307
3628
  onMuxDataUpdate: events?.onMuxDataUpdate
3308
3629
  });
@@ -3336,7 +3657,7 @@ var Player = forwardRef(
3336
3657
  onLoadStart: events?.onLoadStart,
3337
3658
  onCanPlay: events?.onCanPlay
3338
3659
  });
3339
- const { uiRef, initializeUI, destroyUI } = useShakaUI(
3660
+ const { uiRef, initializeUI } = useShakaUI(
3340
3661
  playerRef,
3341
3662
  containerRef,
3342
3663
  videoRef,
@@ -3389,43 +3710,105 @@ var Player = forwardRef(
3389
3710
  }
3390
3711
  }
3391
3712
  };
3392
- const initializeChromecast = () => {
3393
- if (!chromecastConfig?.enabled) {
3394
- return;
3395
- }
3396
- try {
3397
- if (events?.onCastStateChange) {
3398
- setTimeout(() => events.onCastStateChange(false), 100);
3399
- }
3400
- } catch (error) {
3401
- console.warn("Chromecast initialization failed:", error);
3402
- }
3403
- };
3404
3713
  useEffect5(() => {
3714
+ console.log("SOURCE IS", src);
3715
+ console.log("\u{1F680} MAIN-INIT: Starting main player initialization sequence...");
3716
+ const initStartTime = performance.now();
3405
3717
  const video = videoRef.current;
3406
- if (!video) return;
3718
+ if (!video) {
3719
+ console.warn("\u{1F680} MAIN-INIT: Video element not available, skipping initialization");
3720
+ return;
3721
+ }
3722
+ console.log("\u{1F680} MAIN-INIT: Video element available, proceeding with initialization");
3407
3723
  const initialize = async () => {
3724
+ if (isInitializingRef.current) {
3725
+ console.log("\u{1F680} MAIN-INIT: Initialization already in progress, skipping...");
3726
+ return;
3727
+ }
3728
+ if (playerRef.current && !playerRef.current.isDestroyed?.()) {
3729
+ console.log("\u{1F680} MAIN-INIT: Player already exists and is not destroyed, loading new source instead of re-initialization");
3730
+ try {
3731
+ const manifestUrl = src.url;
3732
+ console.log("\u{1F680} MAIN-INIT: Loading new manifest:", manifestUrl);
3733
+ await playerRef.current.load(manifestUrl);
3734
+ console.log("\u{1F680} MAIN-INIT: New manifest loaded successfully without re-initialization");
3735
+ isInitializingRef.current = false;
3736
+ return;
3737
+ } catch (error) {
3738
+ if (error && typeof error === "object" && "code" in error && error.code === 7e3) {
3739
+ console.log("\u{1F680} MAIN-INIT: Benign LOAD_INTERRUPTED (7000) while loading new source. Skipping re-init.");
3740
+ isInitializingRef.current = false;
3741
+ return;
3742
+ }
3743
+ console.error("\u{1F680} MAIN-INIT: Failed to load new source, proceeding with full re-initialization:", error);
3744
+ }
3745
+ }
3746
+ isInitializingRef.current = true;
3747
+ console.log("\u{1F680} MAIN-INIT: Setting initialization flag to prevent race conditions");
3408
3748
  try {
3749
+ console.log("\u{1F680} MAIN-INIT: === STEP 1: Initialize Player ===");
3750
+ const playerInitStart = performance.now();
3409
3751
  await initializePlayer(video);
3752
+ const playerInitEnd = performance.now();
3753
+ console.log(`\u{1F680} MAIN-INIT: Player initialization completed in ${(playerInitEnd - playerInitStart).toFixed(2)}ms`);
3754
+ console.log("\u{1F680} MAIN-INIT: === STEP 2: Setup Event Listeners ===");
3755
+ const eventListenersStart = performance.now();
3410
3756
  setupEventListeners();
3757
+ const eventListenersEnd = performance.now();
3758
+ console.log(`\u{1F680} MAIN-INIT: Event listeners setup completed in ${(eventListenersEnd - eventListenersStart).toFixed(2)}ms`);
3759
+ console.log("\u{1F680} MAIN-INIT: === STEP 3: Setup Quality Tracking ===");
3760
+ const qualityStart = performance.now();
3411
3761
  const cleanupQuality = setupQualityTracking();
3412
3762
  configureQuality();
3763
+ const qualityEnd = performance.now();
3764
+ console.log(`\u{1F680} MAIN-INIT: Quality setup completed in ${(qualityEnd - qualityStart).toFixed(2)}ms`);
3765
+ console.log("\u{1F680} MAIN-INIT: === STEP 4: Initialize UI (Including Chromecast) ===");
3766
+ const timeSincePlayerInit = performance.now() - playerInitEnd;
3767
+ console.log(`\u{1F680} MAIN-INIT: RACE CHECK - Time gap between player and UI init: ${timeSincePlayerInit.toFixed(2)}ms`);
3768
+ const uiInitStart = performance.now();
3413
3769
  await initializeUI();
3770
+ const uiInitEnd = performance.now();
3771
+ console.log(`\u{1F680} MAIN-INIT: UI initialization completed in ${(uiInitEnd - uiInitStart).toFixed(2)}ms`);
3772
+ console.log("\u{1F680} MAIN-INIT: === STEP 5: Initialize Ads ===");
3773
+ const adsInitStart = performance.now();
3414
3774
  initializeAds();
3415
- initializeChromecast();
3775
+ const adsInitEnd = performance.now();
3776
+ console.log(`\u{1F680} MAIN-INIT: Ads initialization completed in ${(adsInitEnd - adsInitStart).toFixed(2)}ms`);
3777
+ const totalInitTime = performance.now() - initStartTime;
3778
+ console.log(`\u{1F680} MAIN-INIT: === INITIALIZATION COMPLETE ===`);
3779
+ console.log(`\u{1F680} MAIN-INIT: Total initialization time: ${totalInitTime.toFixed(2)}ms`);
3416
3780
  } catch (error) {
3417
- console.error("Error during player initialization:", error);
3781
+ const errorTime = performance.now() - initStartTime;
3782
+ console.error(`\u{1F680} MAIN-INIT: Error during player initialization after ${errorTime.toFixed(2)}ms:`, error);
3418
3783
  handleMuxError(error);
3784
+ } finally {
3785
+ isInitializingRef.current = false;
3786
+ console.log("\u{1F680} MAIN-INIT: Clearing initialization flag");
3419
3787
  }
3420
3788
  };
3421
3789
  initialize();
3422
3790
  return () => {
3791
+ console.log("\u{1F680} MAIN-CLEANUP: Starting cleanup sequence...");
3792
+ const cleanupStart = performance.now();
3793
+ if (!playerRef.current && !isInitializingRef.current) {
3794
+ console.log("\u{1F680} MAIN-CLEANUP: No player to cleanup and no initialization in progress, skipping cleanup");
3795
+ return;
3796
+ }
3797
+ if (playerRef.current && !playerRef.current.isDestroyed?.()) {
3798
+ console.log("\u{1F680} MAIN-CLEANUP: Player exists and is not destroyed - this might be a source change");
3799
+ console.log("\u{1F680} MAIN-CLEANUP: Checking if this is a real unmount or just a re-render...");
3800
+ }
3801
+ isInitializingRef.current = false;
3802
+ console.log("\u{1F680} MAIN-CLEANUP: Reset initialization flag");
3803
+ console.log("\u{1F680} MAIN-CLEANUP: Cleaning up event listeners...");
3423
3804
  cleanupEventListeners();
3424
- destroyUI();
3805
+ console.log("\u{1F680} MAIN-CLEANUP: Destroying UI...");
3806
+ console.log("\u{1F680} MAIN-CLEANUP: Destroying Mux...");
3425
3807
  destroyMux();
3426
- destroyPlayer();
3808
+ const cleanupEnd = performance.now();
3809
+ console.log(`\u{1F680} MAIN-CLEANUP: Cleanup completed in ${(cleanupEnd - cleanupStart).toFixed(2)}ms`);
3427
3810
  };
3428
- }, [src]);
3811
+ }, [src?.url]);
3429
3812
  useEffect5(() => {
3430
3813
  const video = videoRef.current;
3431
3814
  if (!video) return;
@@ -3488,8 +3871,6 @@ var Player = forwardRef(
3488
3871
  ref: containerRef,
3489
3872
  className: containerClasses,
3490
3873
  style: containerStyle,
3491
- "data-shaka-player-container": true,
3492
- "data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
3493
3874
  children: [
3494
3875
  /* @__PURE__ */ jsx8(
3495
3876
  "video",