@mottosports/motto-video-player 1.0.1-rc.22 → 1.0.1-rc.24

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
@@ -1104,11 +1104,11 @@ styleInject(`/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */
1104
1104
 
1105
1105
  // src/Player.tsx
1106
1106
  import { forwardRef, useEffect as useEffect5, useRef as useRef8, useImperativeHandle } from "react";
1107
- import shaka2 from "shaka-player/dist/shaka-player.ui";
1107
+ import shaka3 from "shaka-player/dist/shaka-player.ui";
1108
1108
 
1109
1109
  // src/hooks/useShakePlayer.ts
1110
1110
  import { useRef, useCallback } from "react";
1111
- import { Player as ShakaPlayer, polyfill } from "shaka-player/dist/shaka-player.ui";
1111
+ import shaka from "shaka-player/dist/shaka-player.ui";
1112
1112
  var useShakePlayer = ({
1113
1113
  src,
1114
1114
  shakaConfig,
@@ -1119,16 +1119,70 @@ var useShakePlayer = ({
1119
1119
  const playerRef = useRef(null);
1120
1120
  const initializePlayer = useCallback(async (video) => {
1121
1121
  try {
1122
- polyfill.installAll();
1123
- if (!ShakaPlayer.isBrowserSupported()) {
1122
+ shaka.polyfill.installAll();
1123
+ if (!shaka.Player.isBrowserSupported()) {
1124
1124
  throw new Error("Browser not supported by Shaka Player");
1125
1125
  }
1126
- const player = new ShakaPlayer();
1126
+ const player = new shaka.Player();
1127
1127
  playerRef.current = player;
1128
1128
  await player.attach(video);
1129
1129
  if (shakaConfig) {
1130
1130
  player.configure(shakaConfig);
1131
1131
  }
1132
+ const isPlaylistObject = typeof src === "object" && src !== null && src.dvr;
1133
+ const manifestUrl = isPlaylistObject ? src.url : src;
1134
+ const drmData = isPlaylistObject ? src.dvr : null;
1135
+ if (drmData && drmData.token) {
1136
+ const isAppleDevice2 = () => {
1137
+ if (typeof navigator === "undefined") return false;
1138
+ const ua = navigator.userAgent || "";
1139
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
1140
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
1141
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
1142
+ return isIOS || isMacSafari;
1143
+ };
1144
+ const useFairPlay = isAppleDevice2();
1145
+ const drmConfig2 = {
1146
+ servers: {},
1147
+ advanced: {}
1148
+ };
1149
+ if (useFairPlay && drmData.fairplay?.license_url) {
1150
+ drmConfig2.servers["com.apple.fps"] = drmData.fairplay.license_url;
1151
+ } else if (drmData.widevine?.license_url) {
1152
+ drmConfig2.servers["com.widevine.alpha"] = drmData.widevine.license_url;
1153
+ }
1154
+ if (useFairPlay && drmData.fairplay?.certificate_url) {
1155
+ try {
1156
+ const req = await fetch(drmData.fairplay.certificate_url);
1157
+ const cert = await req.arrayBuffer();
1158
+ drmConfig2.advanced["com.apple.fps"] = {
1159
+ serverCertificate: new Uint8Array(cert)
1160
+ };
1161
+ } catch (e) {
1162
+ console.warn("Failed to fetch FairPlay certificate:", e);
1163
+ }
1164
+ }
1165
+ if (Object.keys(drmConfig2.servers).length > 0) {
1166
+ player.configure({ drm: drmConfig2 });
1167
+ }
1168
+ const netEngine = player.getNetworkingEngine();
1169
+ if (netEngine) {
1170
+ netEngine.registerRequestFilter((type, request) => {
1171
+ if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
1172
+ request.headers["x-dt-custom-data"] = drmData.token;
1173
+ }
1174
+ });
1175
+ netEngine.registerResponseFilter((type, response) => {
1176
+ if (type === shaka.net.NetworkingEngine.RequestType.LICENSE) {
1177
+ const ks = player.keySystem && player.keySystem();
1178
+ if (ks === "com.apple.fps") {
1179
+ const responseText = shaka.util.StringUtils.fromUTF8(response.data);
1180
+ response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
1181
+ }
1182
+ }
1183
+ });
1184
+ }
1185
+ }
1132
1186
  if (drmConfig) {
1133
1187
  if (drmConfig.clearKeys) {
1134
1188
  player.configure({ "drm.clearKeys": drmConfig.clearKeys });
@@ -1145,7 +1199,7 @@ var useShakePlayer = ({
1145
1199
  console.error("Shaka Player Error:", error);
1146
1200
  onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
1147
1201
  });
1148
- await player.load(src);
1202
+ await player.load(manifestUrl);
1149
1203
  onPlayerReady?.(player);
1150
1204
  return player;
1151
1205
  } catch (error) {
@@ -1292,10 +1346,10 @@ var useSkipControls = (videoRef, onSkipBack, onSkipForward) => {
1292
1346
  // src/hooks/useMuxAnalytics.ts
1293
1347
  import { useCallback as useCallback4, useRef as useRef3 } from "react";
1294
1348
  import initShakaPlayerMux from "@mux/mux-data-shakaplayer";
1295
- import shaka from "shaka-player/dist/shaka-player.ui";
1349
+ import shaka2 from "shaka-player/dist/shaka-player.ui";
1296
1350
 
1297
1351
  // package.json
1298
- var version = "1.0.1-rc.22";
1352
+ var version = "1.0.1-rc.24";
1299
1353
 
1300
1354
  // src/hooks/useMuxAnalytics.ts
1301
1355
  var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
@@ -1322,7 +1376,7 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
1322
1376
  ...muxConfig.metadata
1323
1377
  }
1324
1378
  };
1325
- shakaPlayerMuxRef.current = initShakaPlayerMux(playerRef.current, muxOptions, shaka);
1379
+ shakaPlayerMuxRef.current = initShakaPlayerMux(playerRef.current, muxOptions, shaka2);
1326
1380
  onMuxReady?.();
1327
1381
  } catch (error) {
1328
1382
  console.error("Failed to initialize Mux Analytics:", error);
@@ -3266,13 +3320,13 @@ var Player = forwardRef(
3266
3320
  if (!imaConfig || !playerRef.current || !videoRef.current) return;
3267
3321
  const adManager = playerRef.current.getAdManager();
3268
3322
  if (!adManager) return;
3269
- adManager.addEventListener(shaka2.ads?.Utils?.AD_STARTED, () => {
3323
+ adManager.addEventListener(shaka3.ads?.Utils?.AD_STARTED, () => {
3270
3324
  events?.onAdStart?.();
3271
3325
  });
3272
- adManager.addEventListener(shaka2.ads?.Utils?.AD_COMPLETE, () => {
3326
+ adManager.addEventListener(shaka3.ads?.Utils?.AD_COMPLETE, () => {
3273
3327
  events?.onAdComplete?.();
3274
3328
  });
3275
- adManager.addEventListener(shaka2.ads?.Utils?.AD_ERROR, (event) => {
3329
+ adManager.addEventListener(shaka3.ads?.Utils?.AD_ERROR, (event) => {
3276
3330
  events?.onAdError?.(event.detail);
3277
3331
  });
3278
3332
  if (imaConfig.adTagUrl) {
@@ -3984,6 +4038,14 @@ import { useCallback as useCallback8, useEffect as useEffect8, useState as useSt
3984
4038
  import { twMerge as twMerge4 } from "tailwind-merge";
3985
4039
  import { useQuery as useQuery2 } from "@tanstack/react-query";
3986
4040
  import { Fragment, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
4041
+ var isAppleDevice = () => {
4042
+ if (typeof navigator === "undefined") return false;
4043
+ const ua = navigator.userAgent || navigator.vendor || "";
4044
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
4045
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
4046
+ const isMacSafari = /Macintosh/.test(ua) && isSafari;
4047
+ return isIOS || isMacSafari;
4048
+ };
3987
4049
  var Event = ({
3988
4050
  publicKey,
3989
4051
  eventId,
@@ -4016,6 +4078,7 @@ var Event = ({
4016
4078
  const [activePlaylist, setActivePlaylist] = useState4();
4017
4079
  const [activeVideoId, setActiveVideoId] = useState4();
4018
4080
  const videoIds = eventData?.videoIds ?? [];
4081
+ const [isDRM, setIsDRM] = useState4(false);
4019
4082
  const {
4020
4083
  data: videosData,
4021
4084
  isLoading: videosIsLoading,
@@ -4042,9 +4105,34 @@ var Event = ({
4042
4105
  for (const video of videosWithPlaylists) {
4043
4106
  const hlsPlaylist = findHLSPlaylist(video);
4044
4107
  if (hlsPlaylist?.url) {
4045
- setActivePlaylist(hlsPlaylist.url);
4108
+ const matchedPlaylist = video.playlists?.find((p) => p.url === hlsPlaylist.url);
4109
+ const drm = matchedPlaylist?.dvr;
4110
+ const hasDrm = Boolean(drm?.token);
4111
+ let selectedPlaylist;
4112
+ if (hasDrm) {
4113
+ const useFairPlay = isAppleDevice();
4114
+ if (useFairPlay && drm?.fairplay?.playlist_url && drm?.fairplay?.license_url) {
4115
+ selectedPlaylist = {
4116
+ url: drm.fairplay.playlist_url,
4117
+ format: matchedPlaylist?.format || "HLS",
4118
+ dvr: drm
4119
+ };
4120
+ } else if (drm?.widevine?.playlist_url && drm?.widevine?.license_url) {
4121
+ selectedPlaylist = {
4122
+ url: drm.widevine.playlist_url,
4123
+ format: matchedPlaylist?.format || "HLS",
4124
+ dvr: drm
4125
+ };
4126
+ } else {
4127
+ selectedPlaylist = matchedPlaylist;
4128
+ }
4129
+ } else {
4130
+ selectedPlaylist = hlsPlaylist.url;
4131
+ }
4132
+ setActivePlaylist(selectedPlaylist);
4046
4133
  setActiveVideoId(video.id);
4047
4134
  hlsPlaylistFound = true;
4135
+ setIsDRM(Boolean(hasDrm));
4048
4136
  break;
4049
4137
  }
4050
4138
  }
@@ -4068,6 +4156,11 @@ var Event = ({
4068
4156
  events.onEventData(eventData);
4069
4157
  }
4070
4158
  }, [eventData, events]);
4159
+ useEffect8(() => {
4160
+ if (isDRM) {
4161
+ console.log("DRM is enabled");
4162
+ }
4163
+ }, [isDRM]);
4071
4164
  useEffect8(() => {
4072
4165
  if (events?.onVideoData && activeVideoId && videosData) {
4073
4166
  const activeVideo = videosData.find((video) => video.id === activeVideoId);
@@ -4080,8 +4173,13 @@ var Event = ({
4080
4173
  const [loadingPlaylist, setLoadingPlaylist] = useState4(true);
4081
4174
  const videosDataError = videosData?.some((video) => !!video.error);
4082
4175
  useEffect8(() => {
4083
- if (eventError || videosError || videosDataError) {
4084
- const errorObj = eventError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
4176
+ if (isEventLoading || videosIsLoading || loadingApisState) {
4177
+ return;
4178
+ }
4179
+ const hasPlayablePlaylist = Boolean(activePlaylist);
4180
+ if (eventError || videosError || videosDataError && !hasPlayablePlaylist) {
4181
+ const firstVideoError = videosData?.find((video) => !!video.error)?.error;
4182
+ const errorObj = eventError || videosError || firstVideoError && new Error(firstVideoError) || new Error("default");
4085
4183
  setError(errorObj);
4086
4184
  if (events?.onError) {
4087
4185
  events.onError(errorObj);
@@ -4089,7 +4187,17 @@ var Event = ({
4089
4187
  } else {
4090
4188
  setError(null);
4091
4189
  }
4092
- }, [eventError, videosError, videosDataError, videosData, events]);
4190
+ }, [
4191
+ eventError,
4192
+ videosError,
4193
+ videosDataError,
4194
+ videosData,
4195
+ events,
4196
+ activePlaylist,
4197
+ isEventLoading,
4198
+ videosIsLoading,
4199
+ loadingApisState
4200
+ ]);
4093
4201
  useEffect8(() => {
4094
4202
  const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
4095
4203
  const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;