@mottosports/motto-video-player 1.0.1-rc.8 → 1.0.1-rc.81
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/README.md +39 -0
- package/dist/index.d.mts +246 -66
- package/dist/index.d.ts +246 -66
- package/dist/index.js +2083 -688
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2028 -634
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -6
package/dist/index.js
CHANGED
|
@@ -31,14 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
|
+
BigPlayIcon: () => BigPlayIcon,
|
|
34
35
|
CreativeWork: () => CreativeWork,
|
|
35
36
|
Event: () => Event,
|
|
36
37
|
Player: () => Player,
|
|
37
38
|
QueryProvider: () => QueryProvider,
|
|
39
|
+
SkipBackIcon: () => SkipBackIcon,
|
|
40
|
+
SkipForwardIcon: () => SkipForwardIcon,
|
|
38
41
|
Video: () => Video,
|
|
39
42
|
queryClient: () => queryClient
|
|
40
43
|
});
|
|
41
44
|
module.exports = __toCommonJS(index_exports);
|
|
45
|
+
var import_controls = require("shaka-player/dist/controls.css");
|
|
42
46
|
|
|
43
47
|
// #style-inject:#style-inject
|
|
44
48
|
function styleInject(css, { insertAt } = {}) {
|
|
@@ -62,73 +66,1031 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
// src/
|
|
66
|
-
styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wide: 0.025em;\n --tracking-widest: 0.1em;\n --radius-md: 0.375rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --aspect-video: 16 / 9;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-auto {\n pointer-events: auto;\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .z-10 {\n z-index: 10;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-6 {\n margin: calc(var(--spacing) * 6);\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-3 {\n margin-top: calc(var(--spacing) * 3);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .aspect-video {\n aspect-ratio: var(--aspect-video);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-8 {\n height: calc(var(--spacing) * 8);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-8 {\n width: calc(var(--spacing) * 8);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-full {\n width: 100%;\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .auto-cols-max {\n grid-auto-columns: max-content;\n }\n .grid-flow-col {\n grid-auto-flow: column;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-stretch {\n justify-content: stretch;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-5 {\n gap: calc(var(--spacing) * 5);\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\n }\n .bg-\\[\\#151515\\] {\n background-color: #151515;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-t {\n --tw-gradient-position: to top in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black\\/70 {\n --tw-gradient-from: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-transparent {\n --tw-gradient-to: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .font-mono {\n font-family: var(--font-mono);\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-5xl {\n font-size: var(--text-5xl);\n line-height: var(--tw-leading, var(--text-5xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wide {\n --tw-tracking: var(--tracking-wide);\n letter-spacing: var(--tracking-wide);\n }\n .tracking-widest {\n --tw-tracking: var(--tracking-widest);\n letter-spacing: var(--tracking-widest);\n }\n .text-white {\n color: var(--color-white);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .md\\:rounded-2xl {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl);\n }\n }\n .md\\:rounded-2xl\\! {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl) !important;\n }\n }\n .md\\:text-base {\n @media (width >= 48rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .md\\:text-sm {\n @media (width >= 48rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:text-xl {\n @media (width >= 48rem) {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n}\n@layer components {\n .motto-video-container {\n position: relative;\n width: 100%;\n min-height: 300px;\n }\n @supports (aspect-ratio: 16/9) {\n .motto-video-container {\n min-height: auto;\n }\n }\n .motto-video-responsive {\n position: absolute;\n top: calc(var(--spacing) * 0);\n left: calc(var(--spacing) * 0);\n height: 100%;\n width: 100%;\n }\n .motto-skip-button {\n position: absolute;\n top: calc(1/2 * 100%);\n z-index: 10;\n display: flex;\n height: calc(var(--spacing) * 16);\n width: calc(var(--spacing) * 16);\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n color: var(--color-white);\n opacity: 80%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 110%;\n --tw-scale-y: 110%;\n --tw-scale-z: 110%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n &:hover {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .motto-skip-button-back {\n left: calc(var(--spacing) * 5);\n }\n .motto-skip-button-forward {\n right: calc(var(--spacing) * 5);\n }\n .motto-mobile-controls-overlay {\n position: absolute;\n inset: calc(var(--spacing) * 0);\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 300ms;\n transition-duration: 300ms;\n pointer-events: none;\n }\n .motto-mobile-controls-group {\n display: flex;\n align-items: center;\n gap: calc(var(--spacing) * 8);\n opacity: 100%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: none;\n }\n .motto-mobile-play-button {\n display: flex;\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-play-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-play-button svg {\n height: calc(var(--spacing) * 7);\n width: calc(var(--spacing) * 7);\n }\n .motto-mobile-skip-button {\n display: flex;\n height: calc(var(--spacing) * 10);\n width: calc(var(--spacing) * 10);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-skip-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-skip-button svg {\n height: calc(var(--spacing) * 6);\n width: calc(var(--spacing) * 6);\n }\n}\n@media (min-width: 768px) {\n .motto-mobile-controls-overlay {\n display: none !important;\n }\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-button[title*="Skip back"],\n .shaka-controls-container .shaka-button[title*="Skip forward"],\n .shaka-controls-container .shaka-button[aria-label*="Skip back"],\n .shaka-controls-container .shaka-button[aria-label*="Skip forward"],\n .shaka-controls-container button[title*="Skip back"],\n .shaka-controls-container button[title*="Skip forward"],\n .shaka-controls-container button[aria-label*="Skip back"],\n .shaka-controls-container button[aria-label*="Skip forward"],\n .motto-native-skip-button:not(.motto-mobile-skip-button),\n .motto-skip-back-button:not(.motto-mobile-skip-button),\n .motto-skip-forward-button:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button),\n button[title*="Skip back"]:not(.motto-mobile-skip-button),\n button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button) {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n width: 0 !important;\n height: 0 !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n .motto-mobile-skip-button {\n display: flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n.shaka-seek-bar-container {\n height: 6px !important;\n width: 100% !important;\n margin: 8px 0 !important;\n border-radius: 4px !important;\n position: relative !important;\n border-top: none !important;\n border-bottom: none !important;\n box-shadow: none !important;\n}\n.shaka-seek-bar {\n height: 6px !important;\n width: 100% !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n background: transparent !important;\n cursor: pointer !important;\n border: none !important;\n outline: none !important;\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n border-radius: 4px !important;\n}\n.shaka-seek-bar::-webkit-slider-runnable-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-moz-range-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-webkit-slider-thumb {\n -webkit-appearance: none !important;\n appearance: none !important;\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.shaka-seek-bar::-moz-range-thumb {\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.motto-skip-back-button,\n.motto-skip-forward-button,\n.motto-native-skip-button {\n background: transparent !important;\n border: none !important;\n padding: 4px !important;\n margin: 0px !important;\n cursor: pointer !important;\n color: #ffffff !important;\n transition: all 0.2s ease !important;\n min-width: 32px !important;\n height: 32px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n border-radius: 4px !important;\n width: 25px;\n}\n.motto-skip-back-button:hover,\n.motto-skip-forward-button:hover,\n.motto-native-skip-button:hover {\n opacity: 0.8 !important;\n background: transparent !important;\n transform: scale(1.05) !important;\n}\n.motto-skip-back-button:active,\n.motto-skip-forward-button:active,\n.motto-native-skip-button:active {\n transform: scale(0.95) !important;\n}\n.motto-skip-back-button svg,\n.motto-skip-forward-button svg,\n.motto-native-skip-button svg {\n width: 24px !important;\n height: 24px !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-play-button,\n .shaka-controls-container .shaka-pause-button {\n display: none !important;\n }\n}\n.shaka-spinner-svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-spinner-path {\n stroke: white !important;\n fill: none !important;\n}\n.shaka-spinner-container {\n color: white !important;\n}\n.shaka-buffering-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner path {\n stroke: white !important;\n fill: none !important;\n}\n[data-shaka-player-container] .shaka-spinner,\n[data-shaka-player-container] .spinner {\n color: white !important;\n border-color: white !important;\n}\n.material-icons.shaka-spinner {\n color: white !important;\n}\n.shaka-controls-container .shaka-spinner,\n.shaka-video-container .shaka-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner svg,\n.shaka-video-container .shaka-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner path,\n.shaka-video-container .shaka-spinner path {\n stroke: white !important;\n}\n.motto-video-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n linear-gradient(\n 135deg,\n #1a1a1a 0%,\n #2d2d2d 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: opacity 0.3s ease;\n}\n.motto-video-loading-overlay.hidden {\n opacity: 0;\n pointer-events: none;\n}\n.motto-video-loading-content {\n text-align: center;\n color: white;\n}\n.motto-video-loading-icon {\n width: 64px;\n height: 64px;\n margin-bottom: 16px;\n opacity: 0.7;\n}\n.motto-video-loading-text {\n font-size: 16px;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.motto-video-loading-subtext {\n font-size: 14px;\n opacity: 0.7;\n}\n@keyframes pulse-live {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n.shaka-play-button-container {\n display: none !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container {\n z-index: 90 !important;\n height: 100px !important;\n bottom: 0 !important;\n top: unset !important;\n }\n}\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-tracking { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-translate-x { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-y { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-z { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
|
|
69
|
+
// src/styles.css
|
|
70
|
+
styleInject(`@layer components {
|
|
71
|
+
video::-webkit-media-controls {
|
|
72
|
+
display: none !important;
|
|
73
|
+
}
|
|
74
|
+
video::-webkit-media-controls-panel {
|
|
75
|
+
display: none !important;
|
|
76
|
+
}
|
|
77
|
+
video::-webkit-media-controls-play-button {
|
|
78
|
+
display: none !important;
|
|
79
|
+
}
|
|
80
|
+
video::-webkit-media-controls-timeline {
|
|
81
|
+
display: none !important;
|
|
82
|
+
}
|
|
83
|
+
video::-webkit-media-controls-current-time-display {
|
|
84
|
+
display: none !important;
|
|
85
|
+
}
|
|
86
|
+
video::-webkit-media-controls-time-remaining-display {
|
|
87
|
+
display: none !important;
|
|
88
|
+
}
|
|
89
|
+
video::-webkit-media-controls-mute-button {
|
|
90
|
+
display: none !important;
|
|
91
|
+
}
|
|
92
|
+
video::-webkit-media-controls-volume-slider {
|
|
93
|
+
display: none !important;
|
|
94
|
+
}
|
|
95
|
+
video::-webkit-media-controls-fullscreen-button {
|
|
96
|
+
display: none !important;
|
|
97
|
+
}
|
|
98
|
+
video::-webkit-media-controls-overlay-play-button {
|
|
99
|
+
display: none !important;
|
|
100
|
+
}
|
|
101
|
+
video::-moz-media-controls {
|
|
102
|
+
display: none !important;
|
|
103
|
+
}
|
|
104
|
+
video {
|
|
105
|
+
outline: none !important;
|
|
106
|
+
}
|
|
107
|
+
video[controls] {
|
|
108
|
+
-webkit-appearance: none !important;
|
|
109
|
+
appearance: none !important;
|
|
110
|
+
}
|
|
111
|
+
video::-webkit-media-controls-enclosure {
|
|
112
|
+
display: none !important;
|
|
113
|
+
}
|
|
114
|
+
video::-webkit-media-controls-start-playback-button {
|
|
115
|
+
display: none !important;
|
|
116
|
+
}
|
|
117
|
+
video[controls]::-webkit-media-controls,
|
|
118
|
+
video[controls]::-webkit-media-controls-panel,
|
|
119
|
+
video[controls]::-webkit-media-controls-play-button,
|
|
120
|
+
video[controls]::-webkit-media-controls-timeline,
|
|
121
|
+
video[controls]::-webkit-media-controls-current-time-display,
|
|
122
|
+
video[controls]::-webkit-media-controls-time-remaining-display,
|
|
123
|
+
video[controls]::-webkit-media-controls-mute-button,
|
|
124
|
+
video[controls]::-webkit-media-controls-volume-slider,
|
|
125
|
+
video[controls]::-webkit-media-controls-fullscreen-button,
|
|
126
|
+
video[controls]::-webkit-media-controls-overlay-play-button,
|
|
127
|
+
video[controls]::-webkit-media-controls-enclosure,
|
|
128
|
+
video[controls]::-webkit-media-controls-start-playback-button {
|
|
129
|
+
display: none !important;
|
|
130
|
+
visibility: hidden !important;
|
|
131
|
+
opacity: 0 !important;
|
|
132
|
+
pointer-events: none !important;
|
|
133
|
+
}
|
|
134
|
+
video[controls]::-moz-media-controls {
|
|
135
|
+
display: none !important;
|
|
136
|
+
visibility: hidden !important;
|
|
137
|
+
opacity: 0 !important;
|
|
138
|
+
}
|
|
139
|
+
.motto-video-container {
|
|
140
|
+
@apply relative w-full;
|
|
141
|
+
min-height: 300px;
|
|
142
|
+
}
|
|
143
|
+
@supports (aspect-ratio: 16/9) {
|
|
144
|
+
.motto-video-container {
|
|
145
|
+
min-height: auto;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
.motto-video-responsive {
|
|
149
|
+
@apply absolute top-0 left-0 w-full h-full;
|
|
150
|
+
}
|
|
151
|
+
.motto-skip-button {
|
|
152
|
+
@apply absolute top-1/2 -translate-y-1/2 bg-black/70 text-white border-0 rounded-full w-16 h-16 text-2xl cursor-pointer flex items-center justify-center transition-all duration-200 z-10 opacity-80 hover:opacity-100 hover:scale-110 active:scale-95;
|
|
153
|
+
}
|
|
154
|
+
.motto-skip-button-back {
|
|
155
|
+
@apply left-5;
|
|
156
|
+
}
|
|
157
|
+
.motto-skip-button-forward {
|
|
158
|
+
@apply right-5;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
.shaka-seek-bar-container {
|
|
162
|
+
height: 6px !important;
|
|
163
|
+
width: 100% !important;
|
|
164
|
+
margin: 8px 0 !important;
|
|
165
|
+
border-radius: 4px !important;
|
|
166
|
+
position: relative !important;
|
|
167
|
+
border-top: none !important;
|
|
168
|
+
border-bottom: none !important;
|
|
169
|
+
box-shadow: none !important;
|
|
170
|
+
}
|
|
171
|
+
.shaka-seek-bar {
|
|
172
|
+
height: 6px !important;
|
|
173
|
+
width: 100% !important;
|
|
174
|
+
-webkit-appearance: none !important;
|
|
175
|
+
appearance: none !important;
|
|
176
|
+
background: transparent !important;
|
|
177
|
+
cursor: pointer !important;
|
|
178
|
+
border: none !important;
|
|
179
|
+
outline: none !important;
|
|
180
|
+
position: absolute !important;
|
|
181
|
+
top: 0 !important;
|
|
182
|
+
left: 0 !important;
|
|
183
|
+
border-radius: 4px !important;
|
|
184
|
+
}
|
|
185
|
+
.shaka-seek-bar::-webkit-slider-runnable-track {
|
|
186
|
+
height: 6px !important;
|
|
187
|
+
background: transparent !important;
|
|
188
|
+
border-radius: 4px !important;
|
|
189
|
+
border: none !important;
|
|
190
|
+
}
|
|
191
|
+
.shaka-seek-bar::-moz-range-track {
|
|
192
|
+
height: 6px !important;
|
|
193
|
+
background: transparent !important;
|
|
194
|
+
border-radius: 4px !important;
|
|
195
|
+
border: none !important;
|
|
196
|
+
}
|
|
197
|
+
.shaka-seek-bar::-webkit-slider-thumb {
|
|
198
|
+
-webkit-appearance: none !important;
|
|
199
|
+
appearance: none !important;
|
|
200
|
+
width: 16px !important;
|
|
201
|
+
height: 16px !important;
|
|
202
|
+
border-radius: 50% !important;
|
|
203
|
+
background: #ffffff !important;
|
|
204
|
+
cursor: pointer !important;
|
|
205
|
+
border: 2px solid #ffffff !important;
|
|
206
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
|
|
207
|
+
margin-top: -4px !important;
|
|
208
|
+
}
|
|
209
|
+
.shaka-seek-bar::-moz-range-thumb {
|
|
210
|
+
width: 16px !important;
|
|
211
|
+
height: 16px !important;
|
|
212
|
+
border-radius: 50% !important;
|
|
213
|
+
background: #ffffff !important;
|
|
214
|
+
cursor: pointer !important;
|
|
215
|
+
border: 2px solid #ffffff !important;
|
|
216
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;
|
|
217
|
+
margin-top: -4px !important;
|
|
218
|
+
}
|
|
219
|
+
.motto-skip-back-button,
|
|
220
|
+
.motto-skip-forward-button,
|
|
221
|
+
.motto-native-skip-button {
|
|
222
|
+
background: transparent !important;
|
|
223
|
+
border: none !important;
|
|
224
|
+
padding: 4px !important;
|
|
225
|
+
margin: 0px !important;
|
|
226
|
+
cursor: pointer !important;
|
|
227
|
+
color: #ffffff !important;
|
|
228
|
+
transition: all 0.2s ease !important;
|
|
229
|
+
min-width: 32px !important;
|
|
230
|
+
height: 32px !important;
|
|
231
|
+
display: flex !important;
|
|
232
|
+
align-items: center !important;
|
|
233
|
+
justify-content: center !important;
|
|
234
|
+
border-radius: 4px !important;
|
|
235
|
+
width: 25px;
|
|
236
|
+
}
|
|
237
|
+
.motto-skip-back-button:hover,
|
|
238
|
+
.motto-skip-forward-button:hover,
|
|
239
|
+
.motto-native-skip-button:hover {
|
|
240
|
+
opacity: 0.8 !important;
|
|
241
|
+
background: transparent !important;
|
|
242
|
+
transform: scale(1.05) !important;
|
|
243
|
+
}
|
|
244
|
+
.motto-skip-back-button:active,
|
|
245
|
+
.motto-skip-forward-button:active,
|
|
246
|
+
.motto-native-skip-button:active {
|
|
247
|
+
transform: scale(0.95) !important;
|
|
248
|
+
}
|
|
249
|
+
.motto-skip-back-button svg,
|
|
250
|
+
.motto-skip-forward-button svg,
|
|
251
|
+
.motto-native-skip-button svg {
|
|
252
|
+
width: 24px !important;
|
|
253
|
+
height: 24px !important;
|
|
254
|
+
}
|
|
255
|
+
.shaka-spinner-svg {
|
|
256
|
+
color: white !important;
|
|
257
|
+
fill: white !important;
|
|
258
|
+
}
|
|
259
|
+
.shaka-spinner-path {
|
|
260
|
+
stroke: white !important;
|
|
261
|
+
fill: none !important;
|
|
262
|
+
}
|
|
263
|
+
.shaka-spinner-container {
|
|
264
|
+
color: white !important;
|
|
265
|
+
}
|
|
266
|
+
.shaka-buffering-spinner {
|
|
267
|
+
color: white !important;
|
|
268
|
+
fill: white !important;
|
|
269
|
+
}
|
|
270
|
+
.shaka-buffering-spinner svg {
|
|
271
|
+
color: white !important;
|
|
272
|
+
fill: white !important;
|
|
273
|
+
}
|
|
274
|
+
.shaka-buffering-spinner path {
|
|
275
|
+
stroke: white !important;
|
|
276
|
+
fill: none !important;
|
|
277
|
+
}
|
|
278
|
+
[data-shaka-player-container] .shaka-spinner,
|
|
279
|
+
[data-shaka-player-container] .spinner {
|
|
280
|
+
color: white !important;
|
|
281
|
+
border-color: white !important;
|
|
282
|
+
}
|
|
283
|
+
.material-icons.shaka-spinner {
|
|
284
|
+
color: white !important;
|
|
285
|
+
}
|
|
286
|
+
.shaka-controls-container .shaka-spinner,
|
|
287
|
+
.shaka-video-container .shaka-spinner {
|
|
288
|
+
color: white !important;
|
|
289
|
+
fill: white !important;
|
|
290
|
+
}
|
|
291
|
+
.shaka-controls-container .shaka-spinner svg,
|
|
292
|
+
.shaka-video-container .shaka-spinner svg {
|
|
293
|
+
color: white !important;
|
|
294
|
+
fill: white !important;
|
|
295
|
+
}
|
|
296
|
+
.shaka-controls-container .shaka-spinner path,
|
|
297
|
+
.shaka-video-container .shaka-spinner path {
|
|
298
|
+
stroke: white !important;
|
|
299
|
+
}
|
|
300
|
+
.motto-video-loading-overlay {
|
|
301
|
+
position: absolute;
|
|
302
|
+
top: 0;
|
|
303
|
+
left: 0;
|
|
304
|
+
width: 100%;
|
|
305
|
+
height: 100%;
|
|
306
|
+
background:
|
|
307
|
+
linear-gradient(
|
|
308
|
+
135deg,
|
|
309
|
+
#1a1a1a 0%,
|
|
310
|
+
#2d2d2d 100%);
|
|
311
|
+
display: flex;
|
|
312
|
+
flex-direction: column;
|
|
313
|
+
align-items: center;
|
|
314
|
+
justify-content: center;
|
|
315
|
+
z-index: 10;
|
|
316
|
+
transition: opacity 0.3s ease;
|
|
317
|
+
}
|
|
318
|
+
.motto-video-loading-overlay.hidden {
|
|
319
|
+
opacity: 0;
|
|
320
|
+
pointer-events: none;
|
|
321
|
+
}
|
|
322
|
+
.motto-video-loading-content {
|
|
323
|
+
text-align: center;
|
|
324
|
+
color: white;
|
|
325
|
+
}
|
|
326
|
+
.motto-video-loading-icon {
|
|
327
|
+
width: 64px;
|
|
328
|
+
height: 64px;
|
|
329
|
+
margin-bottom: 16px;
|
|
330
|
+
opacity: 0.7;
|
|
331
|
+
}
|
|
332
|
+
.motto-video-loading-text {
|
|
333
|
+
font-size: 16px;
|
|
334
|
+
font-weight: 500;
|
|
335
|
+
margin-bottom: 8px;
|
|
336
|
+
}
|
|
337
|
+
.motto-video-loading-subtext {
|
|
338
|
+
font-size: 14px;
|
|
339
|
+
opacity: 0.7;
|
|
340
|
+
}
|
|
341
|
+
@keyframes pulse-live {
|
|
342
|
+
0% {
|
|
343
|
+
opacity: 1;
|
|
344
|
+
transform: scale(1);
|
|
345
|
+
}
|
|
346
|
+
50% {
|
|
347
|
+
opacity: 0.7;
|
|
348
|
+
transform: scale(1.1);
|
|
349
|
+
}
|
|
350
|
+
100% {
|
|
351
|
+
opacity: 1;
|
|
352
|
+
transform: scale(1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
.shaka-play-button {
|
|
356
|
+
background: rgba(255, 255, 255, 0.1) !important;
|
|
357
|
+
border: none !important;
|
|
358
|
+
color: white !important;
|
|
359
|
+
padding: 10px !important;
|
|
360
|
+
border-radius: 100% !important;
|
|
361
|
+
transition: all 0.2s ease !important;
|
|
362
|
+
display: flex !important;
|
|
363
|
+
align-items: center !important;
|
|
364
|
+
justify-content: center !important;
|
|
365
|
+
min-width: 55px !important;
|
|
366
|
+
height: 55px !important;
|
|
367
|
+
}
|
|
368
|
+
.shaka-play-button-container {
|
|
369
|
+
background: transparent;
|
|
370
|
+
transition: all 0.2s ease !important;
|
|
371
|
+
}
|
|
372
|
+
.motto-video-container:not(.no-cursor) .shaka-play-button-container {
|
|
373
|
+
background: rgba(0, 0, 0, 0.3);
|
|
374
|
+
transition: all 0.s ease !important;
|
|
375
|
+
}
|
|
376
|
+
.shaka-play-button:hover {
|
|
377
|
+
background: rgba(255, 255, 255, 0.2) !important;
|
|
378
|
+
transform: scale(1.05) !important;
|
|
379
|
+
}
|
|
380
|
+
.shaka-play-button:active {
|
|
381
|
+
transform: scale(0.95) !important;
|
|
382
|
+
}
|
|
383
|
+
.shaka-play-button > * {
|
|
384
|
+
display: none !important;
|
|
385
|
+
}
|
|
386
|
+
.shaka-play-button::after {
|
|
387
|
+
content: "" !important;
|
|
388
|
+
width: 35px !important;
|
|
389
|
+
height: 35px !important;
|
|
390
|
+
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
|
|
391
|
+
background-repeat: no-repeat !important;
|
|
392
|
+
background-size: contain !important;
|
|
393
|
+
background-position: center !important;
|
|
394
|
+
display: block !important;
|
|
395
|
+
}
|
|
396
|
+
.shaka-play-button[aria-label*=Play]::after {
|
|
397
|
+
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" /></svg>') !important;
|
|
398
|
+
}
|
|
399
|
+
.shaka-play-button[aria-label*=Pause]::after {
|
|
400
|
+
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" /></svg>') !important;
|
|
401
|
+
}
|
|
402
|
+
.motto-video-container {
|
|
403
|
+
background: #111111;
|
|
404
|
+
}
|
|
405
|
+
.motto-video-container video {
|
|
406
|
+
width: 100% !important;
|
|
407
|
+
height: 100% !important;
|
|
408
|
+
margin-left: auto !important;
|
|
409
|
+
margin-right: auto !important;
|
|
410
|
+
}
|
|
411
|
+
html[dir=rtl] .shaka-controls-container,
|
|
412
|
+
html[dir=rtl] .shaka-bottom-controls,
|
|
413
|
+
html[dir=rtl] .shaka-controls-button-panel {
|
|
414
|
+
direction: ltr !important;
|
|
415
|
+
}
|
|
416
|
+
html[dir=rtl] .shaka-overflow-menu,
|
|
417
|
+
html[dir=rtl] .shaka-settings-menu {
|
|
418
|
+
direction: rtl !important;
|
|
419
|
+
text-align: right !important;
|
|
420
|
+
}
|
|
421
|
+
html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:not(:first-child) {
|
|
422
|
+
margin-right: 12px !important;
|
|
423
|
+
margin-left: 0 !important;
|
|
424
|
+
}
|
|
425
|
+
html[dir=rtl] .shaka-overflow-menu .shaka-overflow-button .material-svg-icon:first-child {
|
|
426
|
+
margin-right: 0 !important;
|
|
427
|
+
margin-left: 12px !important;
|
|
428
|
+
}
|
|
429
|
+
.shaka-hidden-fast-forward-container,
|
|
430
|
+
.shaka-hidden-rewind-container {
|
|
431
|
+
pointer-events: none !important;
|
|
432
|
+
display: none !important;
|
|
433
|
+
}
|
|
434
|
+
`);
|
|
67
435
|
|
|
68
436
|
// src/Player.tsx
|
|
69
|
-
var
|
|
437
|
+
var import_react12 = require("react");
|
|
70
438
|
var import_shaka_player4 = __toESM(require("shaka-player/dist/shaka-player.ui"));
|
|
71
439
|
|
|
72
|
-
// src/hooks/
|
|
440
|
+
// src/hooks/useShakaPlayer.ts
|
|
73
441
|
var import_react = require("react");
|
|
74
|
-
var import_shaka_player = require("shaka-player/dist/shaka-player.ui");
|
|
75
|
-
|
|
442
|
+
var import_shaka_player = __toESM(require("shaka-player/dist/shaka-player.ui"));
|
|
443
|
+
|
|
444
|
+
// src/utils/devices.ts
|
|
445
|
+
var isAppleDevice = () => {
|
|
446
|
+
if (typeof navigator === "undefined") return false;
|
|
447
|
+
const ua = navigator.userAgent || "";
|
|
448
|
+
const isIOS = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
449
|
+
const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|Edg/.test(ua);
|
|
450
|
+
const isMacSafari = /Macintosh/.test(ua) && isSafari;
|
|
451
|
+
return isIOS || isMacSafari;
|
|
452
|
+
};
|
|
453
|
+
var isPlayReadySupported = () => {
|
|
454
|
+
if (typeof navigator === "undefined" || typeof window === "undefined") {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
if (!navigator.requestMediaKeySystemAccess) {
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
const userAgent = navigator.userAgent || "";
|
|
461
|
+
const isXbox = /Xbox/.test(userAgent);
|
|
462
|
+
const isEdge = /Edg/.test(userAgent);
|
|
463
|
+
const isIE = /Trident|MSIE/.test(userAgent);
|
|
464
|
+
const isWindows = /Windows/.test(userAgent);
|
|
465
|
+
return isXbox || (isEdge || isIE) && isWindows;
|
|
466
|
+
};
|
|
467
|
+
var supportsWidevinePersistentLicenses = () => {
|
|
468
|
+
return false;
|
|
469
|
+
if (typeof navigator === "undefined") {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
const userAgent = navigator.userAgent || "";
|
|
473
|
+
const isChromeMatch = userAgent.match(/Chrome\/(\d+)/);
|
|
474
|
+
if (!isChromeMatch) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
if (/Edg|OPR|Opera/.test(userAgent)) {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
const chromeVersion = parseInt(isChromeMatch[1], 10);
|
|
481
|
+
if (chromeVersion < 64) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
const isMacOS = /Mac OS X|Macintosh/.test(userAgent);
|
|
485
|
+
const isWindows = /Windows/.test(userAgent);
|
|
486
|
+
return isMacOS || isWindows;
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// src/hooks/useShakaPlayer.ts
|
|
490
|
+
var import_mux_data_shakaplayer = __toESM(require("@mux/mux-data-shakaplayer"));
|
|
491
|
+
|
|
492
|
+
// package.json
|
|
493
|
+
var version = "1.0.1-rc.81";
|
|
494
|
+
|
|
495
|
+
// src/utils/licenseCache.ts
|
|
496
|
+
var PERSISTENT_LICENSE_PREFIX = "motto_lic_";
|
|
497
|
+
var LICENSE_EXPIRY_MS = 2 * 60 * 60 * 1e3;
|
|
498
|
+
var LICENSE_MAX_RETRY_ATTEMPTS = 10;
|
|
499
|
+
var getAllLicenseCacheKeys = () => {
|
|
500
|
+
const keys = [];
|
|
501
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
502
|
+
const key = localStorage.key(i);
|
|
503
|
+
if (key?.startsWith(PERSISTENT_LICENSE_PREFIX)) {
|
|
504
|
+
keys.push(key);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return keys;
|
|
508
|
+
};
|
|
509
|
+
var getAllLicenseCacheEntries = () => {
|
|
510
|
+
const keys = getAllLicenseCacheKeys();
|
|
511
|
+
const entries = [];
|
|
512
|
+
for (const key of keys) {
|
|
513
|
+
try {
|
|
514
|
+
const stored = localStorage.getItem(key);
|
|
515
|
+
if (stored) {
|
|
516
|
+
const data = JSON.parse(stored);
|
|
517
|
+
entries.push({ key, data });
|
|
518
|
+
}
|
|
519
|
+
} catch (error) {
|
|
520
|
+
console.warn(`Failed to parse license cache entry for key ${key}:`, error);
|
|
521
|
+
localStorage.removeItem(key);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return entries;
|
|
525
|
+
};
|
|
526
|
+
var evictLRUEntry = () => {
|
|
527
|
+
const entries = getAllLicenseCacheEntries();
|
|
528
|
+
if (entries.length === 0) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
entries.sort((a, b) => {
|
|
532
|
+
const oldestA = Math.min(...a.data.map((session) => session.timestamp));
|
|
533
|
+
const oldestB = Math.min(...b.data.map((session) => session.timestamp));
|
|
534
|
+
return oldestA - oldestB;
|
|
535
|
+
});
|
|
536
|
+
const lruEntry = entries[0];
|
|
537
|
+
localStorage.removeItem(lruEntry.key);
|
|
538
|
+
console.log(`Evicted LRU license cache entry: ${lruEntry.key}`);
|
|
539
|
+
return true;
|
|
540
|
+
};
|
|
541
|
+
var storeWithQuotaHandling = (key, data) => {
|
|
542
|
+
let attempts = 0;
|
|
543
|
+
while (attempts < LICENSE_MAX_RETRY_ATTEMPTS) {
|
|
544
|
+
try {
|
|
545
|
+
localStorage.setItem(key, data);
|
|
546
|
+
return true;
|
|
547
|
+
} catch (error) {
|
|
548
|
+
if (error instanceof DOMException && (error.code === 22 || // QUOTA_EXCEEDED_ERR
|
|
549
|
+
error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED")) {
|
|
550
|
+
console.warn(`QuotaExceededError on attempt ${attempts + 1}, attempting LRU eviction...`);
|
|
551
|
+
if (!evictLRUEntry()) {
|
|
552
|
+
console.error("No more entries to evict, storage operation failed");
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
attempts++;
|
|
556
|
+
} else {
|
|
557
|
+
console.error("Failed to store license cache data:", error);
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
console.error(`Failed to store license cache data after ${LICENSE_MAX_RETRY_ATTEMPTS} eviction attempts`);
|
|
563
|
+
return false;
|
|
564
|
+
};
|
|
565
|
+
var managePersistentLicenseStorage = (playlistId, licenseCacheKey, newSessionMetadata) => {
|
|
566
|
+
try {
|
|
567
|
+
const storageKey = `${PERSISTENT_LICENSE_PREFIX}${playlistId}_${licenseCacheKey}`;
|
|
568
|
+
const stored = localStorage.getItem(storageKey);
|
|
569
|
+
let existingSessions = [];
|
|
570
|
+
if (stored) {
|
|
571
|
+
try {
|
|
572
|
+
existingSessions = JSON.parse(stored);
|
|
573
|
+
} catch (parseError) {
|
|
574
|
+
console.warn("Failed to parse existing persistent license data:", parseError);
|
|
575
|
+
existingSessions = [];
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
const now = Date.now();
|
|
579
|
+
let validSessions = existingSessions.filter(
|
|
580
|
+
(session) => now - session.timestamp < LICENSE_EXPIRY_MS
|
|
581
|
+
);
|
|
582
|
+
if (newSessionMetadata && newSessionMetadata.length > 0) {
|
|
583
|
+
const newSessions = newSessionMetadata.map((session) => {
|
|
584
|
+
const uint8Array = new Uint8Array(session.initData);
|
|
585
|
+
const binaryString = Array.from(uint8Array).map((byte) => String.fromCharCode(byte)).join("");
|
|
586
|
+
return {
|
|
587
|
+
sessionId: session.sessionId,
|
|
588
|
+
initData: btoa(binaryString),
|
|
589
|
+
initDataType: session.initDataType,
|
|
590
|
+
keySystem: session.keySystem,
|
|
591
|
+
timestamp: now
|
|
592
|
+
};
|
|
593
|
+
});
|
|
594
|
+
const newSessionIds = new Set(newSessions.map((s) => s.sessionId));
|
|
595
|
+
validSessions = validSessions.filter((session) => !newSessionIds.has(session.sessionId));
|
|
596
|
+
validSessions = [...validSessions, ...newSessions];
|
|
597
|
+
}
|
|
598
|
+
if (validSessions.length === 0) {
|
|
599
|
+
localStorage.removeItem(storageKey);
|
|
600
|
+
} else {
|
|
601
|
+
const dataToStore = JSON.stringify(validSessions);
|
|
602
|
+
const success = storeWithQuotaHandling(storageKey, dataToStore);
|
|
603
|
+
if (!success) {
|
|
604
|
+
console.error(`Failed to store license cache for ${storageKey} after quota handling`);
|
|
605
|
+
return validSessions;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return validSessions;
|
|
609
|
+
} catch (error) {
|
|
610
|
+
console.warn("Failed to manage persistent license storage:", error);
|
|
611
|
+
return [];
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
var storePersistentLicense = (playlistId, licenseCacheKey, sessionMetadata) => {
|
|
615
|
+
managePersistentLicenseStorage(playlistId, licenseCacheKey, sessionMetadata);
|
|
616
|
+
};
|
|
617
|
+
var retrievePersistentLicense = (playlistId, licenseCacheKey) => {
|
|
618
|
+
try {
|
|
619
|
+
const validSessions = managePersistentLicenseStorage(playlistId, licenseCacheKey);
|
|
620
|
+
return validSessions.map((session) => ({
|
|
621
|
+
sessionId: session.sessionId,
|
|
622
|
+
initData: Uint8Array.from(atob(session.initData), (c) => c.charCodeAt(0)).buffer,
|
|
623
|
+
initDataType: session.initDataType,
|
|
624
|
+
keySystem: session.keySystem
|
|
625
|
+
}));
|
|
626
|
+
} catch (error) {
|
|
627
|
+
console.warn("Failed to retrieve persistent license:", error);
|
|
628
|
+
return [];
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
var clearAllPersistentLicenses = () => {
|
|
632
|
+
try {
|
|
633
|
+
const keys = getAllLicenseCacheKeys();
|
|
634
|
+
for (const key of keys) {
|
|
635
|
+
localStorage.removeItem(key);
|
|
636
|
+
}
|
|
637
|
+
console.log(`Cleared ${keys.length} persistent license cache entries`);
|
|
638
|
+
return keys.length;
|
|
639
|
+
} catch (error) {
|
|
640
|
+
console.error("Failed to clear persistent licenses:", error);
|
|
641
|
+
return 0;
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// src/hooks/useShakaPlayer.ts
|
|
646
|
+
var normalizeSource = (src) => {
|
|
647
|
+
if (typeof src === "string") {
|
|
648
|
+
return {
|
|
649
|
+
id: "",
|
|
650
|
+
url: src,
|
|
651
|
+
format: "auto",
|
|
652
|
+
drm: {}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
return src;
|
|
656
|
+
};
|
|
657
|
+
var useShakaPlayer = ({
|
|
76
658
|
src,
|
|
77
659
|
shakaConfig,
|
|
78
660
|
drmConfig,
|
|
79
661
|
onError,
|
|
80
|
-
onPlayerReady
|
|
662
|
+
onPlayerReady,
|
|
663
|
+
muxConfig,
|
|
664
|
+
onMuxReady,
|
|
665
|
+
onMuxDataUpdate,
|
|
666
|
+
publicKey,
|
|
667
|
+
mottoToken,
|
|
668
|
+
hasAds = false,
|
|
669
|
+
hasSystem73 = false,
|
|
670
|
+
apiToken
|
|
81
671
|
}) => {
|
|
82
672
|
const playerRef = (0, import_react.useRef)(null);
|
|
83
|
-
const
|
|
673
|
+
const [isRetrying, setIsRetrying] = (0, import_react.useState)(false);
|
|
674
|
+
const videoElementRef = (0, import_react.useRef)(null);
|
|
675
|
+
const destroyInProgressRef = (0, import_react.useRef)(null);
|
|
676
|
+
const isDestroyingRef = (0, import_react.useRef)(false);
|
|
677
|
+
const initSequenceRef = (0, import_react.useRef)(0);
|
|
678
|
+
const activeInitIdRef = (0, import_react.useRef)(null);
|
|
679
|
+
const waitingForKeyTimerRef = (0, import_react.useRef)(null);
|
|
680
|
+
const waitingForKeyHandlerRef = (0, import_react.useRef)(null);
|
|
681
|
+
const playbackResumedHandlerRef = (0, import_react.useRef)(null);
|
|
682
|
+
const usingPersistentLicenseRef = (0, import_react.useRef)(false);
|
|
683
|
+
const storedPersistentThisLoadRef = (0, import_react.useRef)(false);
|
|
684
|
+
const drmExpirationHandlerRef = (0, import_react.useRef)(null);
|
|
685
|
+
const getManifestUrl = (0, import_react.useCallback)(() => {
|
|
686
|
+
const playlistSrc = normalizeSource(src);
|
|
687
|
+
let manifestUrl = playlistSrc.url;
|
|
688
|
+
const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
|
|
689
|
+
if (isDRM) {
|
|
690
|
+
const isPlayReady = isPlayReadySupported();
|
|
691
|
+
if (isAppleDevice() && playlistSrc.drm?.fairplay?.certificateUrl) {
|
|
692
|
+
manifestUrl = playlistSrc.drm.fairplay.playlistUrl;
|
|
693
|
+
} else if (isPlayReady && playlistSrc.drm?.playready?.licenseUrl) {
|
|
694
|
+
manifestUrl = playlistSrc.drm.playready.playlistUrl;
|
|
695
|
+
} else {
|
|
696
|
+
manifestUrl = playlistSrc.drm?.widevine?.playlistUrl || "";
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return manifestUrl;
|
|
700
|
+
}, [src]);
|
|
701
|
+
const initializePlayerInternal = (0, import_react.useCallback)(async (video) => {
|
|
84
702
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
703
|
+
if (destroyInProgressRef.current) {
|
|
704
|
+
try {
|
|
705
|
+
await destroyInProgressRef.current;
|
|
706
|
+
} catch {
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
const myInitId = ++initSequenceRef.current;
|
|
710
|
+
activeInitIdRef.current = myInitId;
|
|
711
|
+
videoElementRef.current = video;
|
|
712
|
+
import_shaka_player.default.polyfill.installAll();
|
|
713
|
+
if (!import_shaka_player.default.Player.isBrowserSupported()) {
|
|
87
714
|
throw new Error("Browser not supported by Shaka Player");
|
|
88
715
|
}
|
|
89
|
-
|
|
716
|
+
if (isDestroyingRef.current) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
const player = new import_shaka_player.default.Player();
|
|
90
720
|
playerRef.current = player;
|
|
91
721
|
await player.attach(video);
|
|
722
|
+
const defaultConfig = {
|
|
723
|
+
manifest: {
|
|
724
|
+
// Override availability window to allow DVR window to grow from start
|
|
725
|
+
// Set to a very large value (24 hours in seconds) to effectively allow unlimited growth
|
|
726
|
+
availabilityWindowOverride: 86400
|
|
727
|
+
// 24 hours in seconds
|
|
728
|
+
},
|
|
729
|
+
streaming: {
|
|
730
|
+
// Allow seeking to any point within the availability window
|
|
731
|
+
safeSeekOffset: 5,
|
|
732
|
+
// 5 seconds from live edge to prevent buffering
|
|
733
|
+
// Increase tolerance for manifest timing inaccuracies in live streams
|
|
734
|
+
inaccurateManifestTolerance: 2
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
player.configure(defaultConfig);
|
|
92
738
|
if (shakaConfig) {
|
|
93
739
|
player.configure(shakaConfig);
|
|
94
740
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
741
|
+
const playlistSrc = normalizeSource(src);
|
|
742
|
+
const manifestUrl = getManifestUrl();
|
|
743
|
+
let playlistId = playlistSrc.id;
|
|
744
|
+
const isDRM = Boolean(playlistSrc.drm?.widevine || playlistSrc.drm?.fairplay || playlistSrc.drm?.playready);
|
|
745
|
+
storedPersistentThisLoadRef.current = false;
|
|
746
|
+
if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
|
|
747
|
+
try {
|
|
748
|
+
await player.destroy();
|
|
749
|
+
} catch {
|
|
98
750
|
}
|
|
99
|
-
if (
|
|
100
|
-
|
|
751
|
+
if (playerRef.current === player) playerRef.current = null;
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
let storedSessionsMetadata = [];
|
|
755
|
+
if (isDRM && playlistId) {
|
|
756
|
+
storedSessionsMetadata = retrievePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "");
|
|
757
|
+
}
|
|
758
|
+
if (isDRM) {
|
|
759
|
+
const drmConfig2 = {
|
|
760
|
+
servers: {
|
|
761
|
+
"com.widevine.alpha": playlistSrc.drm?.widevine?.licenseUrl,
|
|
762
|
+
"com.microsoft.playready": playlistSrc.drm?.playready?.licenseUrl,
|
|
763
|
+
"com.apple.fps": playlistSrc.drm?.fairplay?.licenseUrl
|
|
764
|
+
},
|
|
765
|
+
keySystemsMapping: {
|
|
766
|
+
// Fall back or reroute to the platform's recommended PlayReady CDM if needed
|
|
767
|
+
"com.microsoft.playready": "com.microsoft.playready.recommendation"
|
|
768
|
+
},
|
|
769
|
+
...playlistSrc.drm?.fairplay && {
|
|
770
|
+
advanced: {
|
|
771
|
+
"com.apple.fps": {
|
|
772
|
+
serverCertificateUri: playlistSrc.drm.fairplay.certificateUrl
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
drmConfig2.advanced = {
|
|
778
|
+
...drmConfig2.advanced,
|
|
779
|
+
"com.widevine.alpha": {
|
|
780
|
+
...drmConfig2.advanced?.["com.widevine.alpha"],
|
|
781
|
+
sessionType: supportsWidevinePersistentLicenses() ? "persistent-license" : "temporary"
|
|
782
|
+
},
|
|
783
|
+
"com.microsoft.playready": {
|
|
784
|
+
...drmConfig2.advanced?.["com.microsoft.playready"],
|
|
785
|
+
sessionType: "persistent-license"
|
|
786
|
+
// PlayReady seems to always require persistent-license (temporary won't work, not compatible with license server response)
|
|
787
|
+
},
|
|
788
|
+
"com.apple.fps": {
|
|
789
|
+
...drmConfig2.advanced?.["com.apple.fps"],
|
|
790
|
+
sessionType: "temporary"
|
|
791
|
+
// FairPlay always uses temporary sessions - Safari won't play with persistent-license
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
if (storedSessionsMetadata.length > 0) {
|
|
795
|
+
drmConfig2.persistentSessionOnlinePlayback = true;
|
|
796
|
+
drmConfig2.persistentSessionsMetadata = storedSessionsMetadata.map((session) => ({
|
|
797
|
+
sessionId: session.sessionId,
|
|
798
|
+
initData: new Uint8Array(session.initData),
|
|
799
|
+
initDataType: session.initDataType
|
|
800
|
+
}));
|
|
801
|
+
}
|
|
802
|
+
usingPersistentLicenseRef.current = storedSessionsMetadata.length > 0;
|
|
803
|
+
player.configure({ drm: drmConfig2 });
|
|
804
|
+
const clearWaitingForKeyTimer = () => {
|
|
805
|
+
if (waitingForKeyTimerRef.current !== null) {
|
|
806
|
+
window.clearTimeout(waitingForKeyTimerRef.current);
|
|
807
|
+
waitingForKeyTimerRef.current = null;
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
const onPlaybackResumed = () => {
|
|
811
|
+
clearWaitingForKeyTimer();
|
|
812
|
+
};
|
|
813
|
+
const onWaitingForKey = () => {
|
|
814
|
+
if (!usingPersistentLicenseRef.current) return;
|
|
815
|
+
if (isRetrying) return;
|
|
816
|
+
clearWaitingForKeyTimer();
|
|
817
|
+
waitingForKeyTimerRef.current = window.setTimeout(async () => {
|
|
818
|
+
try {
|
|
819
|
+
if (isRetrying) return;
|
|
820
|
+
console.warn("Stuck waiting for decryption key; attempting license cache reset and reload...");
|
|
821
|
+
const clearedCount = clearAllPersistentLicenses();
|
|
822
|
+
if (clearedCount > 0 && playerRef.current) {
|
|
823
|
+
setIsRetrying(true);
|
|
824
|
+
await playerRef.current.load(getManifestUrl());
|
|
825
|
+
console.log("Reloaded manifest after clearing cached licenses");
|
|
826
|
+
} else {
|
|
827
|
+
console.warn("No cached licenses found to clear, skipping reload");
|
|
828
|
+
}
|
|
829
|
+
} catch (e) {
|
|
830
|
+
console.error("Failed during recovery from waitingforkey state:", e);
|
|
831
|
+
onError?.(e);
|
|
832
|
+
} finally {
|
|
833
|
+
setIsRetrying(false);
|
|
834
|
+
clearWaitingForKeyTimer();
|
|
835
|
+
}
|
|
836
|
+
}, 3e3);
|
|
837
|
+
};
|
|
838
|
+
try {
|
|
839
|
+
video.addEventListener("waitingforkey", onWaitingForKey);
|
|
840
|
+
video.addEventListener("playing", onPlaybackResumed);
|
|
841
|
+
video.addEventListener("ended", onPlaybackResumed);
|
|
842
|
+
video.addEventListener("pause", onPlaybackResumed);
|
|
843
|
+
waitingForKeyHandlerRef.current = onWaitingForKey;
|
|
844
|
+
playbackResumedHandlerRef.current = onPlaybackResumed;
|
|
845
|
+
} catch (e) {
|
|
846
|
+
console.warn("Failed to attach waitingforkey/playback listeners:", e);
|
|
847
|
+
}
|
|
848
|
+
const netEngine = player.getNetworkingEngine();
|
|
849
|
+
if (netEngine) {
|
|
850
|
+
netEngine.registerRequestFilter((type, request) => {
|
|
851
|
+
switch (type) {
|
|
852
|
+
case import_shaka_player.default.net.NetworkingEngine.RequestType.LICENSE:
|
|
853
|
+
if (publicKey) {
|
|
854
|
+
request.headers["authorization"] = `Bearer ${publicKey}`;
|
|
855
|
+
}
|
|
856
|
+
if (mottoToken) {
|
|
857
|
+
request.headers["x-motto-token"] = mottoToken;
|
|
858
|
+
}
|
|
859
|
+
break;
|
|
860
|
+
case import_shaka_player.default.net.NetworkingEngine.RequestType.MANIFEST:
|
|
861
|
+
case import_shaka_player.default.net.NetworkingEngine.RequestType.SEGMENT:
|
|
862
|
+
request.allowCrossSiteCredentials = true;
|
|
863
|
+
break;
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
netEngine.registerResponseFilter((type, response) => {
|
|
867
|
+
if (type === import_shaka_player.default.net.NetworkingEngine.RequestType.LICENSE) {
|
|
868
|
+
const ks = player.keySystem && player.keySystem();
|
|
869
|
+
if (ks === "com.apple.fps") {
|
|
870
|
+
const responseText = import_shaka_player.default.util.StringUtils.fromUTF8(response.data);
|
|
871
|
+
response.data = import_shaka_player.default.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (apiToken) {
|
|
878
|
+
const netEngine = player.getNetworkingEngine();
|
|
879
|
+
if (netEngine) {
|
|
880
|
+
netEngine.registerRequestFilter((type, request) => {
|
|
881
|
+
if (type === import_shaka_player.default.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
882
|
+
request.headers["authorization"] = `Bearer ${apiToken}`;
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
if (isDRM && playlistId) {
|
|
888
|
+
const onDRMSessionUpdate = () => {
|
|
889
|
+
try {
|
|
890
|
+
if (storedPersistentThisLoadRef.current) return;
|
|
891
|
+
const activeDrmSessions = player.getActiveSessionsMetadata?.();
|
|
892
|
+
if (!activeDrmSessions) return;
|
|
893
|
+
const persistentSessions = activeDrmSessions.filter(
|
|
894
|
+
(session) => session.sessionType === "persistent-license"
|
|
895
|
+
);
|
|
896
|
+
if (persistentSessions.length > 0) {
|
|
897
|
+
const sessionsToStore = persistentSessions.map((session) => ({
|
|
898
|
+
sessionId: session.sessionId,
|
|
899
|
+
initData: session.initData,
|
|
900
|
+
initDataType: session.initDataType,
|
|
901
|
+
keySystem: session.keySystem || "com.widevine.alpha"
|
|
902
|
+
}));
|
|
903
|
+
storePersistentLicense(playlistId, playlistSrc.drm?.licenseCacheKey ?? "", sessionsToStore);
|
|
904
|
+
storedPersistentThisLoadRef.current = true;
|
|
905
|
+
}
|
|
906
|
+
} catch (e) {
|
|
907
|
+
console.warn("Failed to persist licenses on expiration update:", e);
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
try {
|
|
911
|
+
player.addEventListener("drmsessionupdate", onDRMSessionUpdate);
|
|
912
|
+
drmExpirationHandlerRef.current = onDRMSessionUpdate;
|
|
913
|
+
} catch (e) {
|
|
914
|
+
console.warn("Failed to attach drmsessionupdate listener:", e);
|
|
101
915
|
}
|
|
102
916
|
}
|
|
103
|
-
player
|
|
917
|
+
player?.addEventListener("error", (event) => {
|
|
104
918
|
const error = event.detail;
|
|
919
|
+
if (error?.code === 7e3) {
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
if (error?.code >= 6e3 && error?.code < 7e3 && !isRetrying && videoElementRef.current) {
|
|
923
|
+
console.warn(`DRM error detected (code: ${error.code}), checking for cached licenses...`);
|
|
924
|
+
const clearedCount = clearAllPersistentLicenses();
|
|
925
|
+
if (clearedCount > 0) {
|
|
926
|
+
console.warn(`Cleared ${clearedCount} cached licenses, retrying...`);
|
|
927
|
+
setIsRetrying(true);
|
|
928
|
+
setTimeout(async () => {
|
|
929
|
+
try {
|
|
930
|
+
const video2 = videoElementRef.current;
|
|
931
|
+
const currentPlayer = playerRef.current;
|
|
932
|
+
if (video2 && currentPlayer) {
|
|
933
|
+
console.log("Reloading manifest after license cache clear...");
|
|
934
|
+
await currentPlayer.load(getManifestUrl());
|
|
935
|
+
console.log("Manifest reloaded successfully");
|
|
936
|
+
}
|
|
937
|
+
} catch (retryError) {
|
|
938
|
+
console.error("Failed to retry after license clear:", retryError);
|
|
939
|
+
onError?.(retryError);
|
|
940
|
+
} finally {
|
|
941
|
+
setIsRetrying(false);
|
|
942
|
+
}
|
|
943
|
+
}, 500);
|
|
944
|
+
return;
|
|
945
|
+
} else {
|
|
946
|
+
console.warn(`No cached licenses found to clear for error code ${error.code}, not retrying to avoid infinite loop`);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
105
949
|
console.error("Shaka Player Error:", error);
|
|
106
950
|
onError?.(new Error(`Shaka Player Error: ${error.message || "Unknown error"}`));
|
|
107
951
|
});
|
|
108
|
-
|
|
952
|
+
if (muxConfig) {
|
|
953
|
+
try {
|
|
954
|
+
const playerInitTime = import_mux_data_shakaplayer.default.utils.now();
|
|
955
|
+
const muxOptions = {
|
|
956
|
+
debug: muxConfig.debug || false,
|
|
957
|
+
disableCookies: muxConfig.disableCookies || false,
|
|
958
|
+
respectDoNotTrack: muxConfig.respectDoNotTrack || false,
|
|
959
|
+
automaticErrorTracking: muxConfig.automaticErrorTracking !== false,
|
|
960
|
+
...muxConfig.beaconCollectionDomain && { beaconCollectionDomain: muxConfig.beaconCollectionDomain },
|
|
961
|
+
...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
|
|
962
|
+
data: {
|
|
963
|
+
env_key: muxConfig.envKey,
|
|
964
|
+
player_name: muxConfig?.metadata?.player_name,
|
|
965
|
+
player_version: version,
|
|
966
|
+
player_init_time: playerInitTime,
|
|
967
|
+
video_title: muxConfig?.metadata?.video_title ?? "",
|
|
968
|
+
video_id: muxConfig?.metadata?.video_id ?? "",
|
|
969
|
+
viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
|
|
970
|
+
...muxConfig.metadata
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
(0, import_mux_data_shakaplayer.default)(player, muxOptions, import_shaka_player.default);
|
|
974
|
+
onMuxReady?.();
|
|
975
|
+
} catch (error) {
|
|
976
|
+
console.error("Failed to initialize Mux Analytics:", error);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
if (activeInitIdRef.current !== myInitId || isDestroyingRef.current) {
|
|
980
|
+
try {
|
|
981
|
+
await player.destroy();
|
|
982
|
+
} catch {
|
|
983
|
+
}
|
|
984
|
+
if (playerRef.current === player) playerRef.current = null;
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
if (!hasAds && !hasSystem73) {
|
|
988
|
+
console.log("\u{1F4FA} [Shaka] Auto-loading manifest:", manifestUrl);
|
|
989
|
+
await player.load(manifestUrl);
|
|
990
|
+
console.log("\u2705 [Shaka] Manifest auto-loaded successfully");
|
|
991
|
+
} else {
|
|
992
|
+
console.log("\u23ED\uFE0F [Shaka] Skipping auto-load (hasAds:", hasAds, ", hasSystem73:", hasSystem73, ")");
|
|
993
|
+
}
|
|
109
994
|
onPlayerReady?.(player);
|
|
110
995
|
return player;
|
|
111
996
|
} catch (error) {
|
|
997
|
+
if (error?.code === 7e3) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
112
1000
|
console.error("Error initializing Shaka Player:", error);
|
|
113
1001
|
onError?.(error);
|
|
114
1002
|
throw error;
|
|
115
1003
|
}
|
|
116
|
-
}, [shakaConfig, drmConfig, src, onError, onPlayerReady]);
|
|
1004
|
+
}, [shakaConfig, drmConfig, src, onError, onPlayerReady, muxConfig, onMuxReady, isRetrying, getManifestUrl, apiToken]);
|
|
1005
|
+
const initializePlayer = (0, import_react.useCallback)(async (video) => {
|
|
1006
|
+
return initializePlayerInternal(video);
|
|
1007
|
+
}, [initializePlayerInternal]);
|
|
1008
|
+
const loadManifest = (0, import_react.useCallback)(async () => {
|
|
1009
|
+
const player = playerRef.current;
|
|
1010
|
+
if (!player) {
|
|
1011
|
+
console.warn("\u26A0\uFE0F [Shaka] Cannot load manifest: player not initialized");
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
try {
|
|
1015
|
+
const manifestUrl = getManifestUrl();
|
|
1016
|
+
console.log("\u{1F4FA} [Shaka] Loading manifest:", manifestUrl);
|
|
1017
|
+
await player.load(manifestUrl);
|
|
1018
|
+
console.log("\u2705 [Shaka] Manifest loaded successfully");
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
if (error?.code === 7e3) {
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
console.error("\u274C [Shaka] Error loading manifest:", error);
|
|
1024
|
+
onError?.(error);
|
|
1025
|
+
throw error;
|
|
1026
|
+
}
|
|
1027
|
+
}, [getManifestUrl, onError]);
|
|
117
1028
|
const destroyPlayer = (0, import_react.useCallback)(async () => {
|
|
118
|
-
|
|
1029
|
+
const playerInstance = playerRef.current;
|
|
1030
|
+
if (playerInstance) {
|
|
119
1031
|
try {
|
|
120
|
-
|
|
1032
|
+
isDestroyingRef.current = true;
|
|
1033
|
+
activeInitIdRef.current = null;
|
|
1034
|
+
if (videoElementRef.current) {
|
|
1035
|
+
try {
|
|
1036
|
+
if (waitingForKeyHandlerRef.current) {
|
|
1037
|
+
videoElementRef.current.removeEventListener("waitingforkey", waitingForKeyHandlerRef.current);
|
|
1038
|
+
}
|
|
1039
|
+
if (playbackResumedHandlerRef.current) {
|
|
1040
|
+
videoElementRef.current.removeEventListener("playing", playbackResumedHandlerRef.current);
|
|
1041
|
+
videoElementRef.current.removeEventListener("ended", playbackResumedHandlerRef.current);
|
|
1042
|
+
videoElementRef.current.removeEventListener("pause", playbackResumedHandlerRef.current);
|
|
1043
|
+
}
|
|
1044
|
+
} catch (e) {
|
|
1045
|
+
console.warn("Error removing media event listeners:", e);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
if (waitingForKeyTimerRef.current !== null) {
|
|
1049
|
+
window.clearTimeout(waitingForKeyTimerRef.current);
|
|
1050
|
+
waitingForKeyTimerRef.current = null;
|
|
1051
|
+
}
|
|
1052
|
+
try {
|
|
1053
|
+
if (drmExpirationHandlerRef.current && playerInstance.removeEventListener) {
|
|
1054
|
+
playerInstance.removeEventListener("drmsessionupdate", drmExpirationHandlerRef.current);
|
|
1055
|
+
}
|
|
1056
|
+
} catch (e) {
|
|
1057
|
+
console.warn("Error removing DRM expiration listener:", e);
|
|
1058
|
+
} finally {
|
|
1059
|
+
drmExpirationHandlerRef.current = null;
|
|
1060
|
+
}
|
|
1061
|
+
const performDestroy = async () => {
|
|
1062
|
+
try {
|
|
1063
|
+
await playerInstance.destroy();
|
|
1064
|
+
} finally {
|
|
1065
|
+
try {
|
|
1066
|
+
if (videoElementRef.current) {
|
|
1067
|
+
videoElementRef.current.removeAttribute("src");
|
|
1068
|
+
videoElementRef.current.load();
|
|
1069
|
+
}
|
|
1070
|
+
} catch {
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
destroyInProgressRef.current = performDestroy();
|
|
1075
|
+
await destroyInProgressRef.current;
|
|
121
1076
|
} catch (error) {
|
|
122
1077
|
console.warn("Error destroying Shaka Player:", error);
|
|
123
1078
|
} finally {
|
|
124
|
-
playerRef.current
|
|
1079
|
+
if (playerRef.current === playerInstance) {
|
|
1080
|
+
playerRef.current = null;
|
|
1081
|
+
}
|
|
1082
|
+
storedPersistentThisLoadRef.current = false;
|
|
1083
|
+
isDestroyingRef.current = false;
|
|
1084
|
+
destroyInProgressRef.current = null;
|
|
125
1085
|
}
|
|
126
1086
|
}
|
|
127
|
-
}, []);
|
|
1087
|
+
}, [playerRef]);
|
|
128
1088
|
return {
|
|
129
1089
|
playerRef,
|
|
130
1090
|
initializePlayer,
|
|
131
|
-
|
|
1091
|
+
loadManifest,
|
|
1092
|
+
destroyPlayer,
|
|
1093
|
+
isRetrying
|
|
132
1094
|
};
|
|
133
1095
|
};
|
|
134
1096
|
|
|
@@ -151,11 +1113,25 @@ var useQualityControl = (playerRef, qualityConfig, onQualityChange) => {
|
|
|
151
1113
|
if (!playerRef.current) return;
|
|
152
1114
|
if (height === 0) {
|
|
153
1115
|
playerRef.current.configure({
|
|
154
|
-
abr: {
|
|
1116
|
+
abr: {
|
|
1117
|
+
enabled: true,
|
|
1118
|
+
switchInterval: 2,
|
|
1119
|
+
// quicker re-checks
|
|
1120
|
+
clearBufferSwitch: true,
|
|
1121
|
+
safeMarginSwitch: 10
|
|
1122
|
+
// leave ~10 s in front of the playhead }
|
|
1123
|
+
}
|
|
155
1124
|
});
|
|
156
1125
|
} else {
|
|
157
1126
|
playerRef.current.configure({
|
|
158
|
-
abr: {
|
|
1127
|
+
abr: {
|
|
1128
|
+
enabled: false,
|
|
1129
|
+
switchInterval: 2,
|
|
1130
|
+
// quicker re-checks
|
|
1131
|
+
clearBufferSwitch: true,
|
|
1132
|
+
safeMarginSwitch: 10
|
|
1133
|
+
// leave ~10 s in front of the playhead }
|
|
1134
|
+
}
|
|
159
1135
|
});
|
|
160
1136
|
const tracks = playerRef.current.getVariantTracks();
|
|
161
1137
|
const targetTrack = tracks.find((track) => track.height === height);
|
|
@@ -234,14 +1210,14 @@ var useSkipControls = (videoRef, onSkipBack, onSkipForward) => {
|
|
|
234
1210
|
|
|
235
1211
|
// src/hooks/useMuxAnalytics.ts
|
|
236
1212
|
var import_react4 = require("react");
|
|
237
|
-
var
|
|
1213
|
+
var import_mux_data_shakaplayer2 = __toESM(require("@mux/mux-data-shakaplayer"));
|
|
238
1214
|
var import_shaka_player2 = __toESM(require("shaka-player/dist/shaka-player.ui"));
|
|
239
1215
|
var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
|
|
240
1216
|
const shakaPlayerMuxRef = (0, import_react4.useRef)(null);
|
|
241
1217
|
const initializeMux = (0, import_react4.useCallback)(() => {
|
|
242
1218
|
if (!muxConfig || !playerRef.current) return;
|
|
243
1219
|
try {
|
|
244
|
-
const playerInitTime =
|
|
1220
|
+
const playerInitTime = import_mux_data_shakaplayer2.default.utils.now();
|
|
245
1221
|
const muxOptions = {
|
|
246
1222
|
debug: muxConfig.debug || false,
|
|
247
1223
|
disableCookies: muxConfig.disableCookies || false,
|
|
@@ -251,13 +1227,16 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
|
|
|
251
1227
|
...muxConfig.errorTranslator && { errorTranslator: muxConfig.errorTranslator },
|
|
252
1228
|
data: {
|
|
253
1229
|
env_key: muxConfig.envKey,
|
|
254
|
-
player_name:
|
|
255
|
-
player_version:
|
|
1230
|
+
player_name: muxConfig?.metadata?.player_name,
|
|
1231
|
+
player_version: version,
|
|
256
1232
|
player_init_time: playerInitTime,
|
|
1233
|
+
video_title: muxConfig?.metadata?.video_title ?? "",
|
|
1234
|
+
video_id: muxConfig?.metadata?.video_id ?? "",
|
|
1235
|
+
viewer_user_id: muxConfig?.metadata?.viewer_user_id ?? "",
|
|
257
1236
|
...muxConfig.metadata
|
|
258
1237
|
}
|
|
259
1238
|
};
|
|
260
|
-
shakaPlayerMuxRef.current = (0,
|
|
1239
|
+
shakaPlayerMuxRef.current = (0, import_mux_data_shakaplayer2.default)(playerRef.current, muxOptions, import_shaka_player2.default);
|
|
261
1240
|
onMuxReady?.();
|
|
262
1241
|
} catch (error) {
|
|
263
1242
|
console.error("Failed to initialize Mux Analytics:", error);
|
|
@@ -300,10 +1279,157 @@ var useMuxAnalytics = (playerRef, muxConfig, onMuxReady, onMuxDataUpdate) => {
|
|
|
300
1279
|
};
|
|
301
1280
|
|
|
302
1281
|
// src/hooks/useShakaUI.ts
|
|
303
|
-
var
|
|
1282
|
+
var import_react6 = require("react");
|
|
304
1283
|
var import_shaka_player3 = require("shaka-player/dist/shaka-player.ui");
|
|
1284
|
+
|
|
1285
|
+
// src/icons/SkipBackIcon.tsx
|
|
1286
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1287
|
+
var SkipBackIcon = ({ size = 24, className = "" }) => {
|
|
1288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1289
|
+
"svg",
|
|
1290
|
+
{
|
|
1291
|
+
width: size,
|
|
1292
|
+
height: size,
|
|
1293
|
+
strokeWidth: "2",
|
|
1294
|
+
viewBox: "0 0 24 24",
|
|
1295
|
+
fill: "none",
|
|
1296
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1297
|
+
className,
|
|
1298
|
+
children: [
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1300
|
+
"path",
|
|
1301
|
+
{
|
|
1302
|
+
d: "M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4",
|
|
1303
|
+
stroke: "currentColor",
|
|
1304
|
+
strokeWidth: "2",
|
|
1305
|
+
strokeLinecap: "round",
|
|
1306
|
+
strokeLinejoin: "round"
|
|
1307
|
+
}
|
|
1308
|
+
),
|
|
1309
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1310
|
+
"path",
|
|
1311
|
+
{
|
|
1312
|
+
d: "M9 9L9 16",
|
|
1313
|
+
stroke: "currentColor",
|
|
1314
|
+
strokeWidth: "2",
|
|
1315
|
+
strokeLinecap: "round",
|
|
1316
|
+
strokeLinejoin: "round"
|
|
1317
|
+
}
|
|
1318
|
+
),
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1320
|
+
"path",
|
|
1321
|
+
{
|
|
1322
|
+
d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
|
|
1323
|
+
stroke: "currentColor",
|
|
1324
|
+
strokeWidth: "2",
|
|
1325
|
+
strokeLinecap: "round",
|
|
1326
|
+
strokeLinejoin: "round"
|
|
1327
|
+
}
|
|
1328
|
+
),
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1330
|
+
"path",
|
|
1331
|
+
{
|
|
1332
|
+
d: "M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6",
|
|
1333
|
+
stroke: "currentColor",
|
|
1334
|
+
strokeWidth: "2",
|
|
1335
|
+
strokeLinecap: "round",
|
|
1336
|
+
strokeLinejoin: "round"
|
|
1337
|
+
}
|
|
1338
|
+
)
|
|
1339
|
+
]
|
|
1340
|
+
}
|
|
1341
|
+
);
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
// src/icons/SkipForwardIcon.tsx
|
|
1345
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1346
|
+
var SkipForwardIcon = ({ size = 24, className = "" }) => {
|
|
1347
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1348
|
+
"svg",
|
|
1349
|
+
{
|
|
1350
|
+
width: size,
|
|
1351
|
+
height: size,
|
|
1352
|
+
strokeWidth: "2",
|
|
1353
|
+
viewBox: "0 0 24 24",
|
|
1354
|
+
fill: "none",
|
|
1355
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1356
|
+
className,
|
|
1357
|
+
children: [
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1359
|
+
"path",
|
|
1360
|
+
{
|
|
1361
|
+
d: "M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4",
|
|
1362
|
+
stroke: "currentColor",
|
|
1363
|
+
strokeLinecap: "round",
|
|
1364
|
+
strokeLinejoin: "round"
|
|
1365
|
+
}
|
|
1366
|
+
),
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1368
|
+
"path",
|
|
1369
|
+
{
|
|
1370
|
+
d: "M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6",
|
|
1371
|
+
stroke: "currentColor",
|
|
1372
|
+
strokeLinecap: "round",
|
|
1373
|
+
strokeLinejoin: "round"
|
|
1374
|
+
}
|
|
1375
|
+
),
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1377
|
+
"path",
|
|
1378
|
+
{
|
|
1379
|
+
d: "M9 9L9 16",
|
|
1380
|
+
stroke: "currentColor",
|
|
1381
|
+
strokeLinecap: "round",
|
|
1382
|
+
strokeLinejoin: "round"
|
|
1383
|
+
}
|
|
1384
|
+
),
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1386
|
+
"path",
|
|
1387
|
+
{
|
|
1388
|
+
d: "M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16",
|
|
1389
|
+
stroke: "currentColor",
|
|
1390
|
+
strokeLinecap: "round",
|
|
1391
|
+
strokeLinejoin: "round"
|
|
1392
|
+
}
|
|
1393
|
+
)
|
|
1394
|
+
]
|
|
1395
|
+
}
|
|
1396
|
+
);
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
// src/icons/BigPlayIcon.tsx
|
|
1400
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1401
|
+
var BigPlayIcon = ({ size = 40, className = "" }) => {
|
|
1402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1403
|
+
"svg",
|
|
1404
|
+
{
|
|
1405
|
+
width: size,
|
|
1406
|
+
height: size,
|
|
1407
|
+
viewBox: "0 0 24 24",
|
|
1408
|
+
fill: "currentColor",
|
|
1409
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1410
|
+
className,
|
|
1411
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1412
|
+
"path",
|
|
1413
|
+
{
|
|
1414
|
+
fillRule: "evenodd",
|
|
1415
|
+
d: "M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z",
|
|
1416
|
+
clipRule: "evenodd"
|
|
1417
|
+
}
|
|
1418
|
+
)
|
|
1419
|
+
}
|
|
1420
|
+
);
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
// src/utils/renderIcon.ts
|
|
1424
|
+
var import_server = require("react-dom/server");
|
|
1425
|
+
var import_react5 = require("react");
|
|
1426
|
+
var renderIcon = (Component, props = {}) => {
|
|
1427
|
+
return (0, import_server.renderToStaticMarkup)((0, import_react5.createElement)(Component, props));
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
// src/hooks/useShakaUI.ts
|
|
305
1431
|
var SkipBackButton = class {
|
|
306
|
-
constructor(parent, controls, onSkipBack) {
|
|
1432
|
+
constructor(parent, controls, onSkipBack, iconSize = 24) {
|
|
307
1433
|
this.parent = parent;
|
|
308
1434
|
this.controls = controls;
|
|
309
1435
|
this.eventManager = { listen: (element, event, handler) => {
|
|
@@ -311,14 +1437,7 @@ var SkipBackButton = class {
|
|
|
311
1437
|
} };
|
|
312
1438
|
this.button_ = document.createElement("button");
|
|
313
1439
|
this.button_.className = "shaka-button motto-native-skip-button";
|
|
314
|
-
this.button_.innerHTML =
|
|
315
|
-
<svg width="24px" stroke-width="2" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
316
|
-
<path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
317
|
-
<path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
318
|
-
<path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
319
|
-
<path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
320
|
-
</svg>
|
|
321
|
-
`;
|
|
1440
|
+
this.button_.innerHTML = renderIcon(SkipBackIcon, { size: iconSize });
|
|
322
1441
|
this.button_.title = "Skip back 15 seconds";
|
|
323
1442
|
this.button_.setAttribute("aria-label", "Skip back 15 seconds");
|
|
324
1443
|
this.parent.appendChild(this.button_);
|
|
@@ -331,9 +1450,13 @@ var SkipBackButton = class {
|
|
|
331
1450
|
}
|
|
332
1451
|
});
|
|
333
1452
|
}
|
|
1453
|
+
// Shaka UI will call `release` when the controls are destroyed.
|
|
1454
|
+
// Provide a no-op implementation to avoid TypeErrors.
|
|
1455
|
+
release() {
|
|
1456
|
+
}
|
|
334
1457
|
};
|
|
335
1458
|
var SkipForwardButton = class {
|
|
336
|
-
constructor(parent, controls, onSkipForward) {
|
|
1459
|
+
constructor(parent, controls, onSkipForward, iconSize = 24) {
|
|
337
1460
|
this.parent = parent;
|
|
338
1461
|
this.controls = controls;
|
|
339
1462
|
this.eventManager = { listen: (element, event, handler) => {
|
|
@@ -341,14 +1464,7 @@ var SkipForwardButton = class {
|
|
|
341
1464
|
} };
|
|
342
1465
|
this.button_ = document.createElement("button");
|
|
343
1466
|
this.button_.className = "shaka-button motto-native-skip-button";
|
|
344
|
-
this.button_.innerHTML =
|
|
345
|
-
<svg fill="none" height="24" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
|
346
|
-
<path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
347
|
-
<path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
348
|
-
<path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
349
|
-
<path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
350
|
-
</svg>
|
|
351
|
-
`;
|
|
1467
|
+
this.button_.innerHTML = renderIcon(SkipForwardIcon, { size: iconSize });
|
|
352
1468
|
this.button_.title = "Skip forward 15 seconds";
|
|
353
1469
|
this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
|
|
354
1470
|
this.parent.appendChild(this.button_);
|
|
@@ -361,243 +1477,65 @@ var SkipForwardButton = class {
|
|
|
361
1477
|
}
|
|
362
1478
|
});
|
|
363
1479
|
}
|
|
1480
|
+
release() {
|
|
1481
|
+
}
|
|
364
1482
|
};
|
|
365
1483
|
var SkipBackButtonFactory = class {
|
|
366
|
-
constructor(onSkipBack) {
|
|
1484
|
+
constructor(onSkipBack, iconSize) {
|
|
367
1485
|
this.onSkipBack = onSkipBack;
|
|
1486
|
+
this.iconSize = iconSize;
|
|
368
1487
|
}
|
|
369
1488
|
create(rootElement, controls) {
|
|
370
|
-
return new SkipBackButton(rootElement, controls, this.onSkipBack);
|
|
1489
|
+
return new SkipBackButton(rootElement, controls, this.onSkipBack, this.iconSize);
|
|
371
1490
|
}
|
|
372
1491
|
};
|
|
373
1492
|
var SkipForwardButtonFactory = class {
|
|
374
|
-
constructor(onSkipForward) {
|
|
375
|
-
this.onSkipForward = onSkipForward;
|
|
376
|
-
}
|
|
377
|
-
create(rootElement, controls) {
|
|
378
|
-
return new SkipForwardButton(rootElement, controls, this.onSkipForward);
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
var MobilePlayButton = class {
|
|
382
|
-
constructor(parent, controls) {
|
|
383
|
-
this.parent = parent;
|
|
384
|
-
this.controls = controls;
|
|
385
|
-
this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
|
|
386
|
-
if (!this.video) {
|
|
387
|
-
console.error("MobilePlayButton: No video element found");
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
this.eventManager = { listen: (element, event, handler) => {
|
|
391
|
-
element.addEventListener(event, handler);
|
|
392
|
-
} };
|
|
393
|
-
this.button_ = document.createElement("button");
|
|
394
|
-
this.button_.className = "motto-mobile-play-button";
|
|
395
|
-
this.updateIcon();
|
|
396
|
-
this.parent.appendChild(this.button_);
|
|
397
|
-
this.eventManager.listen(this.button_, "click", () => {
|
|
398
|
-
if (this.video.paused) {
|
|
399
|
-
this.video.play();
|
|
400
|
-
} else {
|
|
401
|
-
this.video.pause();
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
this.eventManager.listen(this.video, "play", () => this.updateIcon());
|
|
405
|
-
this.eventManager.listen(this.video, "pause", () => this.updateIcon());
|
|
406
|
-
}
|
|
407
|
-
updateIcon() {
|
|
408
|
-
if (this.video.paused) {
|
|
409
|
-
this.button_.innerHTML = `
|
|
410
|
-
<svg xmlns="http://www.w3.org/2000/svg" stroke-width="2" viewBox="0 0 24 24" fill="currentColor">
|
|
411
|
-
<path stroke-width="2" fill-rule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clip-rule="evenodd" />
|
|
412
|
-
</svg>
|
|
413
|
-
`;
|
|
414
|
-
this.button_.setAttribute("aria-label", "Play");
|
|
415
|
-
} else {
|
|
416
|
-
this.button_.innerHTML = `
|
|
417
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
418
|
-
<path fill-rule="evenodd" d="M6.75 5.25a.75.75 0 0 1 .75-.75H9a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H7.5a.75.75 0 0 1-.75-.75V5.25Zm7.5 0A.75.75 0 0 1 15 4.5h1.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V5.25Z" clip-rule="evenodd" />
|
|
419
|
-
</svg>
|
|
420
|
-
`;
|
|
421
|
-
this.button_.setAttribute("aria-label", "Pause");
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
var MobileSkipBackButton = class {
|
|
426
|
-
constructor(parent, controls, onSkipBack) {
|
|
427
|
-
this.parent = parent;
|
|
428
|
-
this.controls = controls;
|
|
429
|
-
this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
|
|
430
|
-
if (!this.video) {
|
|
431
|
-
console.error("MobileSkipBackButton: No video element found");
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
this.eventManager = { listen: (element, event, handler) => {
|
|
435
|
-
element.addEventListener(event, handler);
|
|
436
|
-
} };
|
|
437
|
-
this.button_ = document.createElement("button");
|
|
438
|
-
this.button_.className = "motto-mobile-skip-button";
|
|
439
|
-
this.button_.innerHTML = `
|
|
440
|
-
<svg width="20px" stroke-width="2" height="20px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
441
|
-
<path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
442
|
-
<path d="M9 9L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
443
|
-
<path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
444
|
-
<path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
445
|
-
</svg>
|
|
446
|
-
`;
|
|
447
|
-
this.button_.setAttribute("aria-label", "Skip back 15 seconds");
|
|
448
|
-
this.parent.appendChild(this.button_);
|
|
449
|
-
this.eventManager.listen(this.button_, "click", () => {
|
|
450
|
-
const newTime = Math.max(0, this.video.currentTime - 15);
|
|
451
|
-
this.video.currentTime = newTime;
|
|
452
|
-
onSkipBack?.(newTime);
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
var MobileSkipForwardButton = class {
|
|
457
|
-
constructor(parent, controls, onSkipForward) {
|
|
458
|
-
this.parent = parent;
|
|
459
|
-
this.controls = controls;
|
|
460
|
-
this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
|
|
461
|
-
if (!this.video) {
|
|
462
|
-
console.error("MobileSkipForwardButton: No video element found");
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
this.eventManager = { listen: (element, event, handler) => {
|
|
466
|
-
element.addEventListener(event, handler);
|
|
467
|
-
} };
|
|
468
|
-
this.button_ = document.createElement("button");
|
|
469
|
-
this.button_.className = "motto-mobile-skip-button";
|
|
470
|
-
this.button_.innerHTML = `
|
|
471
|
-
<svg fill="none" height="20" stroke-width="2" viewBox="0 0 24 24" width="20" xmlns="http://www.w3.org/2000/svg">
|
|
472
|
-
<path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
473
|
-
<path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
474
|
-
<path d="M9 9L9 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
475
|
-
<path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
476
|
-
</svg>
|
|
477
|
-
`;
|
|
478
|
-
this.button_.setAttribute("aria-label", "Skip forward 15 seconds");
|
|
479
|
-
this.parent.appendChild(this.button_);
|
|
480
|
-
this.eventManager.listen(this.button_, "click", () => {
|
|
481
|
-
const newTime = Math.min(this.video.duration || 0, this.video.currentTime + 15);
|
|
482
|
-
this.video.currentTime = newTime;
|
|
483
|
-
onSkipForward?.(newTime);
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
};
|
|
487
|
-
var MobileControlsContainer = class {
|
|
488
|
-
constructor(parent, controls, onSkipBack, onSkipForward) {
|
|
489
|
-
this.parent = parent;
|
|
490
|
-
this.controls = controls;
|
|
491
|
-
if (!parent) {
|
|
492
|
-
console.error("MobileControlsContainer: No parent element provided");
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
this.container_ = document.createElement("div");
|
|
496
|
-
this.container_.className = "motto-mobile-controls-overlay";
|
|
497
|
-
const controlsGroup = document.createElement("div");
|
|
498
|
-
controlsGroup.className = "motto-mobile-controls-group";
|
|
499
|
-
new MobileSkipBackButton(controlsGroup, controls, onSkipBack);
|
|
500
|
-
new MobilePlayButton(controlsGroup, controls);
|
|
501
|
-
new MobileSkipForwardButton(controlsGroup, controls, onSkipForward);
|
|
502
|
-
this.container_.appendChild(controlsGroup);
|
|
503
|
-
this.parent.appendChild(this.container_);
|
|
504
|
-
this.setupVisibilitySync();
|
|
505
|
-
}
|
|
506
|
-
setupVisibilitySync() {
|
|
507
|
-
setTimeout(() => {
|
|
508
|
-
this.syncVisibility();
|
|
509
|
-
this.observer = new MutationObserver((mutations) => {
|
|
510
|
-
mutations.forEach((mutation) => {
|
|
511
|
-
if (mutation.type === "attributes" && mutation.attributeName === "class") {
|
|
512
|
-
this.syncVisibility();
|
|
513
|
-
}
|
|
514
|
-
});
|
|
515
|
-
});
|
|
516
|
-
this.observer.observe(this.parent, {
|
|
517
|
-
attributes: true,
|
|
518
|
-
attributeFilter: ["class"]
|
|
519
|
-
});
|
|
520
|
-
const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
|
|
521
|
-
if (video) {
|
|
522
|
-
video.addEventListener("play", () => {
|
|
523
|
-
setTimeout(() => this.syncVisibility(), 50);
|
|
524
|
-
});
|
|
525
|
-
video.addEventListener("pause", () => {
|
|
526
|
-
setTimeout(() => this.syncVisibility(), 50);
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
}, 1e3);
|
|
530
|
-
}
|
|
531
|
-
syncVisibility() {
|
|
532
|
-
const mainContainer = this.parent;
|
|
533
|
-
const hasNoCursor = mainContainer.classList.contains("no-cursor");
|
|
534
|
-
const video = this.controls?.getVideo?.() || this.parent.querySelector("video");
|
|
535
|
-
const isVideoPaused = video ? video.paused : false;
|
|
536
|
-
const isControlsVisible = !hasNoCursor || isVideoPaused;
|
|
537
|
-
if (this.container_) {
|
|
538
|
-
if (isControlsVisible) {
|
|
539
|
-
this.container_.style.opacity = "1";
|
|
540
|
-
this.container_.style.pointerEvents = "none";
|
|
541
|
-
} else {
|
|
542
|
-
this.container_.style.opacity = "0";
|
|
543
|
-
this.container_.style.pointerEvents = "none";
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
isElementVisible(element) {
|
|
548
|
-
const style = window.getComputedStyle(element);
|
|
549
|
-
const hasHiddenClass = element.classList.contains("shaka-hidden") || element.classList.contains("hidden") || element.classList.contains("shaka-fade-out");
|
|
550
|
-
return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && !element.hidden && !hasHiddenClass;
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
var MobileControlsContainerFactory = class {
|
|
554
|
-
constructor(onSkipBack, onSkipForward) {
|
|
555
|
-
this.onSkipBack = onSkipBack;
|
|
1493
|
+
constructor(onSkipForward, iconSize) {
|
|
556
1494
|
this.onSkipForward = onSkipForward;
|
|
1495
|
+
this.iconSize = iconSize;
|
|
557
1496
|
}
|
|
558
1497
|
create(rootElement, controls) {
|
|
559
|
-
return new
|
|
1498
|
+
return new SkipForwardButton(rootElement, controls, this.onSkipForward, this.iconSize);
|
|
560
1499
|
}
|
|
561
1500
|
};
|
|
562
|
-
var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
|
|
563
|
-
const uiRef = (0,
|
|
564
|
-
const registeredElements = (0,
|
|
565
|
-
const initializeUI = (0,
|
|
1501
|
+
var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale = "en") => {
|
|
1502
|
+
const uiRef = (0, import_react6.useRef)(null);
|
|
1503
|
+
const registeredElements = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
|
|
1504
|
+
const initializeUI = (0, import_react6.useCallback)(async () => {
|
|
566
1505
|
if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
|
|
567
1506
|
return null;
|
|
568
1507
|
}
|
|
569
|
-
const isMobile = window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
570
1508
|
if (!registeredElements.current.has("skip_back_button")) {
|
|
571
|
-
import_shaka_player3.ui.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack));
|
|
1509
|
+
import_shaka_player3.ui.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack, iconSizes?.skipButtons));
|
|
572
1510
|
registeredElements.current.add("skip_back_button");
|
|
573
1511
|
}
|
|
574
1512
|
if (!registeredElements.current.has("skip_forward_button")) {
|
|
575
|
-
import_shaka_player3.ui.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward));
|
|
1513
|
+
import_shaka_player3.ui.Controls.registerElement("skip_forward_button", new SkipForwardButtonFactory(onSkipForward, iconSizes?.skipButtons));
|
|
576
1514
|
registeredElements.current.add("skip_forward_button");
|
|
577
1515
|
}
|
|
578
|
-
if (isMobile) {
|
|
579
|
-
if (!registeredElements.current.has("mobile_controls_container")) {
|
|
580
|
-
import_shaka_player3.ui.Controls.registerElement("mobile_controls_container", new MobileControlsContainerFactory(onSkipBack, onSkipForward));
|
|
581
|
-
registeredElements.current.add("mobile_controls_container");
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
1516
|
const ui = new import_shaka_player3.ui.Overlay(playerRef.current, containerRef.current, videoRef.current);
|
|
585
1517
|
uiRef.current = ui;
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
1518
|
+
if (locale !== "en") {
|
|
1519
|
+
try {
|
|
1520
|
+
ui.getControls().getLocalization().changeLocale([locale]);
|
|
1521
|
+
console.log(`Set locale to '${locale}'`);
|
|
1522
|
+
} catch (error) {
|
|
1523
|
+
console.warn(`Failed to set locale to '${locale}', falling back to 'en':`, error);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
const isMobile = window.innerWidth <= 767;
|
|
1527
|
+
const controlPanelElements = [
|
|
1528
|
+
...isMobile ? [] : ["skip_back_button"],
|
|
1529
|
+
...isMobile ? [] : ["play_pause"],
|
|
1530
|
+
...isMobile ? [] : ["skip_forward_button"],
|
|
596
1531
|
"mute",
|
|
597
|
-
"volume",
|
|
1532
|
+
...isMobile ? [] : ["volume"],
|
|
1533
|
+
// Only include volume on desktop
|
|
598
1534
|
"time_and_duration",
|
|
599
1535
|
"spacer",
|
|
600
1536
|
"fullscreen",
|
|
1537
|
+
"cast",
|
|
1538
|
+
// Always show cast button
|
|
601
1539
|
"overflow_menu"
|
|
602
1540
|
];
|
|
603
1541
|
const uiConfig = {
|
|
@@ -610,35 +1548,58 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
|
|
|
610
1548
|
// Progress/played portion (white)
|
|
611
1549
|
},
|
|
612
1550
|
controlPanelElements,
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
1551
|
+
addBigPlayButton: isMobile,
|
|
1552
|
+
// For now, Chromecast via Shaka must use the Motto receiver that runs on the legacy cast SDK (2.0), because
|
|
1553
|
+
// Shaka does not support the newer Cast SDK (3.0+) in its native integration.
|
|
1554
|
+
castReceiverAppId: "EC900D4D",
|
|
1555
|
+
castAndroidReceiverCompatible: true,
|
|
1556
|
+
// Enable Android TV compatibility
|
|
1557
|
+
overflowMenuButtons: [
|
|
1558
|
+
"quality",
|
|
1559
|
+
"picture_in_picture",
|
|
1560
|
+
"playback_rate"
|
|
1561
|
+
]
|
|
617
1562
|
};
|
|
618
|
-
if (chromecastConfig?.receiverApplicationId) {
|
|
619
|
-
uiConfig.castReceiverAppId = chromecastConfig.receiverApplicationId;
|
|
620
|
-
uiConfig.castAndroidReceiverCompatible = false;
|
|
621
|
-
}
|
|
622
1563
|
ui.configure(uiConfig);
|
|
623
1564
|
if (isMobile) {
|
|
624
|
-
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
1565
|
+
const customizeBigPlayButton = () => {
|
|
1566
|
+
const bigPlayButton = containerRef.current?.querySelector(".shaka-big-play-button");
|
|
1567
|
+
if (bigPlayButton && !bigPlayButton.hasAttribute("data-customized")) {
|
|
1568
|
+
const buttonSize = iconSizes?.bigPlayButton || 40;
|
|
1569
|
+
bigPlayButton.innerHTML = renderIcon(BigPlayIcon, { size: buttonSize });
|
|
1570
|
+
bigPlayButton.setAttribute("data-customized", "true");
|
|
1571
|
+
const buttonElement = bigPlayButton;
|
|
1572
|
+
buttonElement.style.display = "flex";
|
|
1573
|
+
buttonElement.style.alignItems = "center";
|
|
1574
|
+
buttonElement.style.justifyContent = "center";
|
|
629
1575
|
}
|
|
630
|
-
}
|
|
1576
|
+
};
|
|
1577
|
+
setTimeout(customizeBigPlayButton, 100);
|
|
1578
|
+
const observer = new MutationObserver(() => {
|
|
1579
|
+
customizeBigPlayButton();
|
|
1580
|
+
});
|
|
1581
|
+
if (containerRef.current) {
|
|
1582
|
+
observer.observe(containerRef.current, {
|
|
1583
|
+
childList: true,
|
|
1584
|
+
subtree: true,
|
|
1585
|
+
attributes: false
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
631
1588
|
}
|
|
632
1589
|
return ui;
|
|
633
|
-
}, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward]);
|
|
634
|
-
const destroyUI = (0,
|
|
635
|
-
|
|
1590
|
+
}, [controls, containerRef, playerRef, videoRef, chromecastConfig, seekbarColors, onSkipBack, onSkipForward, iconSizes, locale]);
|
|
1591
|
+
const destroyUI = (0, import_react6.useCallback)(async () => {
|
|
1592
|
+
const uiInstance = uiRef.current;
|
|
1593
|
+
if (uiInstance) {
|
|
636
1594
|
try {
|
|
637
|
-
|
|
1595
|
+
await uiInstance.destroy();
|
|
638
1596
|
} catch (error) {
|
|
639
1597
|
console.error("Error destroying UI:", error);
|
|
1598
|
+
} finally {
|
|
1599
|
+
if (uiRef.current === uiInstance) {
|
|
1600
|
+
uiRef.current = null;
|
|
1601
|
+
}
|
|
640
1602
|
}
|
|
641
|
-
uiRef.current = null;
|
|
642
1603
|
}
|
|
643
1604
|
}, []);
|
|
644
1605
|
return {
|
|
@@ -649,100 +1610,31 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
|
|
|
649
1610
|
};
|
|
650
1611
|
|
|
651
1612
|
// src/hooks/useEventHandlers.ts
|
|
652
|
-
var
|
|
1613
|
+
var import_react7 = require("react");
|
|
653
1614
|
var useEventHandlers = (videoRef, handlers) => {
|
|
654
|
-
const setupEventListeners = (0,
|
|
1615
|
+
const setupEventListeners = (0, import_react7.useCallback)(() => {
|
|
655
1616
|
const video = videoRef.current;
|
|
656
1617
|
if (!video) return;
|
|
657
1618
|
const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
|
|
658
1619
|
if (onPlay) video.addEventListener("play", onPlay);
|
|
659
1620
|
if (onPause) video.addEventListener("pause", onPause);
|
|
660
|
-
if (onEnded) video.addEventListener("ended", onEnded);
|
|
661
|
-
if (onLoadStart) video.addEventListener("loadstart", onLoadStart);
|
|
662
|
-
if (onCanPlay) video.addEventListener("canplay", onCanPlay);
|
|
663
|
-
}, [videoRef, handlers]);
|
|
664
|
-
const cleanupEventListeners = (0,
|
|
665
|
-
const video = videoRef.current;
|
|
666
|
-
if (!video) return;
|
|
667
|
-
const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
|
|
668
|
-
if (onPlay) video.removeEventListener("play", onPlay);
|
|
669
|
-
if (onPause) video.removeEventListener("pause", onPause);
|
|
670
|
-
if (onEnded) video.removeEventListener("ended", onEnded);
|
|
671
|
-
if (onLoadStart) video.removeEventListener("loadstart", onLoadStart);
|
|
672
|
-
if (onCanPlay) video.removeEventListener("canplay", onCanPlay);
|
|
673
|
-
}, [videoRef, handlers]);
|
|
674
|
-
return {
|
|
675
|
-
setupEventListeners,
|
|
676
|
-
cleanupEventListeners
|
|
677
|
-
};
|
|
678
|
-
};
|
|
679
|
-
|
|
680
|
-
// src/hooks/useLiveBadge.ts
|
|
681
|
-
var import_react7 = require("react");
|
|
682
|
-
var useLiveBadge = (playerRef, options = {}) => {
|
|
683
|
-
const [isLive, setIsLive] = (0, import_react7.useState)(false);
|
|
684
|
-
const [isVisible, setIsVisible] = (0, import_react7.useState)(false);
|
|
685
|
-
const intervalRef = (0, import_react7.useRef)(null);
|
|
686
|
-
const { enabled = true, onLiveStateChange } = options;
|
|
687
|
-
const checkLiveStatus = () => {
|
|
688
|
-
if (!playerRef.current || !enabled) {
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
try {
|
|
692
|
-
const player = playerRef.current;
|
|
693
|
-
if (!player.getManifest || !player.getPresentationTimeline || typeof player.getPresentationTimeline !== "function") {
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
|
-
const manifest = player.getManifest();
|
|
697
|
-
if (!manifest) {
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
const timeline = player.getPresentationTimeline();
|
|
701
|
-
if (!timeline || typeof timeline.isLive !== "function") {
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
const liveStatus = timeline.isLive();
|
|
705
|
-
if (liveStatus !== isLive) {
|
|
706
|
-
setIsLive(liveStatus);
|
|
707
|
-
setIsVisible(liveStatus);
|
|
708
|
-
onLiveStateChange?.(liveStatus);
|
|
709
|
-
}
|
|
710
|
-
} catch (error) {
|
|
711
|
-
if (error instanceof Error && !error.message.includes("not a function")) {
|
|
712
|
-
console.error("Error checking live status:", error);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
};
|
|
716
|
-
(0, import_react7.useEffect)(() => {
|
|
717
|
-
if (!enabled) {
|
|
718
|
-
setIsLive(false);
|
|
719
|
-
setIsVisible(false);
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
checkLiveStatus();
|
|
723
|
-
intervalRef.current = setInterval(checkLiveStatus, 2e3);
|
|
724
|
-
return () => {
|
|
725
|
-
if (intervalRef.current) {
|
|
726
|
-
clearInterval(intervalRef.current);
|
|
727
|
-
intervalRef.current = null;
|
|
728
|
-
}
|
|
729
|
-
};
|
|
730
|
-
}, [enabled, playerRef.current]);
|
|
731
|
-
(0, import_react7.useEffect)(() => {
|
|
732
|
-
return () => {
|
|
733
|
-
if (intervalRef.current) {
|
|
734
|
-
clearInterval(intervalRef.current);
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
}, []);
|
|
738
|
-
const hideBadge = () => setIsVisible(false);
|
|
739
|
-
const showBadge = () => setIsVisible(true);
|
|
1621
|
+
if (onEnded) video.addEventListener("ended", onEnded);
|
|
1622
|
+
if (onLoadStart) video.addEventListener("loadstart", onLoadStart);
|
|
1623
|
+
if (onCanPlay) video.addEventListener("canplay", onCanPlay);
|
|
1624
|
+
}, [videoRef, handlers]);
|
|
1625
|
+
const cleanupEventListeners = (0, import_react7.useCallback)(() => {
|
|
1626
|
+
const video = videoRef.current;
|
|
1627
|
+
if (!video) return;
|
|
1628
|
+
const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
|
|
1629
|
+
if (onPlay) video.removeEventListener("play", onPlay);
|
|
1630
|
+
if (onPause) video.removeEventListener("pause", onPause);
|
|
1631
|
+
if (onEnded) video.removeEventListener("ended", onEnded);
|
|
1632
|
+
if (onLoadStart) video.removeEventListener("loadstart", onLoadStart);
|
|
1633
|
+
if (onCanPlay) video.removeEventListener("canplay", onCanPlay);
|
|
1634
|
+
}, [videoRef, handlers]);
|
|
740
1635
|
return {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
hideBadge,
|
|
744
|
-
showBadge,
|
|
745
|
-
checkLiveStatus
|
|
1636
|
+
setupEventListeners,
|
|
1637
|
+
cleanupEventListeners
|
|
746
1638
|
};
|
|
747
1639
|
};
|
|
748
1640
|
|
|
@@ -751,54 +1643,144 @@ var import_react8 = require("react");
|
|
|
751
1643
|
|
|
752
1644
|
// src/hooks/useLiveIndicator.ts
|
|
753
1645
|
var import_react9 = require("react");
|
|
754
|
-
var useLiveIndicator = (containerRef, options = {}) => {
|
|
1646
|
+
var useLiveIndicator = (containerRef, playerRef, options = {}) => {
|
|
755
1647
|
const observerRef = (0, import_react9.useRef)(null);
|
|
1648
|
+
const intervalRef = (0, import_react9.useRef)(null);
|
|
1649
|
+
const lastStatusRef = (0, import_react9.useRef)(null);
|
|
756
1650
|
const {
|
|
757
1651
|
enabled = true,
|
|
758
1652
|
indicatorColor = "#ff0000",
|
|
759
1653
|
indicatorSize = 8,
|
|
760
|
-
showPulseAnimation = true
|
|
1654
|
+
showPulseAnimation = true,
|
|
1655
|
+
liveThresholdSeconds = 15,
|
|
1656
|
+
onLiveStatusChange
|
|
761
1657
|
} = options;
|
|
1658
|
+
const getLiveStatus = (player) => {
|
|
1659
|
+
if (!player) {
|
|
1660
|
+
return { isLive: false, isNearEdge: false };
|
|
1661
|
+
}
|
|
1662
|
+
try {
|
|
1663
|
+
if (typeof player.isLive !== "function") {
|
|
1664
|
+
return { isLive: false, isNearEdge: false };
|
|
1665
|
+
}
|
|
1666
|
+
const isLiveStream = player.isLive();
|
|
1667
|
+
if (!isLiveStream) return { isLive: false, isNearEdge: false };
|
|
1668
|
+
const videoElement = player.getMediaElement?.();
|
|
1669
|
+
if (!videoElement) return { isLive: true, isNearEdge: false };
|
|
1670
|
+
if (typeof player.seekRange !== "function") {
|
|
1671
|
+
return { isLive: true, isNearEdge: false };
|
|
1672
|
+
}
|
|
1673
|
+
const seekRange = player.seekRange();
|
|
1674
|
+
if (!seekRange || seekRange.end === void 0) {
|
|
1675
|
+
return { isLive: true, isNearEdge: false };
|
|
1676
|
+
}
|
|
1677
|
+
const liveEdge = seekRange.end;
|
|
1678
|
+
const currentTime = videoElement.currentTime;
|
|
1679
|
+
const timeBehindLive = liveEdge - currentTime;
|
|
1680
|
+
return {
|
|
1681
|
+
isLive: true,
|
|
1682
|
+
isNearEdge: timeBehindLive <= liveThresholdSeconds,
|
|
1683
|
+
liveEdge
|
|
1684
|
+
};
|
|
1685
|
+
} catch (error) {
|
|
1686
|
+
console.error("Error checking live status:", error);
|
|
1687
|
+
return { isLive: false, isNearEdge: false };
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
const seekToLiveEdge = () => {
|
|
1691
|
+
const player = playerRef.current;
|
|
1692
|
+
if (!player) return;
|
|
1693
|
+
try {
|
|
1694
|
+
if (typeof player.seekRange !== "function") return;
|
|
1695
|
+
const seekRange = player.seekRange();
|
|
1696
|
+
if (!seekRange || seekRange.end === void 0) return;
|
|
1697
|
+
const liveEdge = seekRange.end;
|
|
1698
|
+
const videoElement = player.getMediaElement?.();
|
|
1699
|
+
if (videoElement) {
|
|
1700
|
+
videoElement.currentTime = liveEdge;
|
|
1701
|
+
}
|
|
1702
|
+
} catch (error) {
|
|
1703
|
+
console.error("Error seeking to live edge:", error);
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
762
1706
|
(0, import_react9.useEffect)(() => {
|
|
763
1707
|
if (!containerRef.current || !enabled) {
|
|
764
1708
|
return;
|
|
765
1709
|
}
|
|
766
|
-
const
|
|
767
|
-
|
|
1710
|
+
const updateLiveIndicator = (currentTimeElement, status) => {
|
|
1711
|
+
const parent = currentTimeElement.parentElement;
|
|
1712
|
+
if (!parent) return;
|
|
1713
|
+
const existingContainer = parent.querySelector(".live-indicator-container");
|
|
1714
|
+
const isCurrentlyNearEdge = existingContainer?.getAttribute("data-near-edge") === "true";
|
|
1715
|
+
if (existingContainer && status.isNearEdge === isCurrentlyNearEdge) {
|
|
768
1716
|
return;
|
|
769
1717
|
}
|
|
1718
|
+
if (existingContainer) {
|
|
1719
|
+
existingContainer.remove();
|
|
1720
|
+
}
|
|
1721
|
+
const container = document.createElement("span");
|
|
1722
|
+
container.className = "live-indicator-container";
|
|
1723
|
+
container.setAttribute("data-near-edge", status.isNearEdge.toString());
|
|
1724
|
+
container.style.cssText = `
|
|
1725
|
+
display: inline-flex;
|
|
1726
|
+
align-items: center;
|
|
1727
|
+
width: 80px;
|
|
1728
|
+
${!status.isNearEdge ? "cursor: pointer;" : ""}
|
|
1729
|
+
`;
|
|
770
1730
|
const indicator = document.createElement("span");
|
|
771
1731
|
indicator.className = "live-indicator-dot";
|
|
772
1732
|
indicator.style.cssText = `
|
|
773
1733
|
display: inline-block;
|
|
774
1734
|
width: ${indicatorSize}px;
|
|
775
1735
|
height: ${indicatorSize}px;
|
|
776
|
-
background-color: ${indicatorColor};
|
|
1736
|
+
background-color: ${status.isNearEdge ? indicatorColor : "#888888"};
|
|
777
1737
|
border-radius: 50%;
|
|
778
1738
|
margin-right: 6px;
|
|
779
|
-
|
|
780
|
-
${showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
|
|
1739
|
+
${status.isNearEdge && showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
|
|
781
1740
|
`;
|
|
782
|
-
|
|
1741
|
+
const liveText = document.createElement("span");
|
|
1742
|
+
liveText.className = "live-indicator-text";
|
|
1743
|
+
liveText.textContent = status.isNearEdge ? "LIVE" : "GO TO LIVE";
|
|
1744
|
+
container.appendChild(indicator);
|
|
1745
|
+
container.appendChild(liveText);
|
|
1746
|
+
if (!status.isNearEdge) {
|
|
1747
|
+
container.addEventListener("click", seekToLiveEdge);
|
|
1748
|
+
}
|
|
1749
|
+
if (status.isNearEdge) {
|
|
1750
|
+
parent.insertBefore(container, currentTimeElement);
|
|
1751
|
+
currentTimeElement.style.display = "none";
|
|
1752
|
+
} else {
|
|
1753
|
+
currentTimeElement.insertAdjacentElement("afterend", container);
|
|
1754
|
+
currentTimeElement.style.display = "";
|
|
1755
|
+
}
|
|
783
1756
|
};
|
|
784
1757
|
const removeLiveIndicator = (currentTimeElement) => {
|
|
785
|
-
const
|
|
786
|
-
if (
|
|
787
|
-
|
|
1758
|
+
const parent = currentTimeElement.parentElement;
|
|
1759
|
+
if (!parent) return;
|
|
1760
|
+
const container = parent.querySelector(".live-indicator-container");
|
|
1761
|
+
if (container) {
|
|
1762
|
+
container.remove();
|
|
1763
|
+
currentTimeElement.style.display = "";
|
|
788
1764
|
}
|
|
789
1765
|
};
|
|
790
1766
|
const checkForLiveContent = () => {
|
|
791
1767
|
const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
|
|
1768
|
+
const status = getLiveStatus(playerRef.current);
|
|
1769
|
+
const lastStatus = lastStatusRef.current;
|
|
1770
|
+
if (onLiveStatusChange && (!lastStatus || lastStatus.isLive !== status.isLive || lastStatus.isNearEdge !== status.isNearEdge)) {
|
|
1771
|
+
onLiveStatusChange(status);
|
|
1772
|
+
lastStatusRef.current = { isLive: status.isLive, isNearEdge: status.isNearEdge };
|
|
1773
|
+
}
|
|
792
1774
|
currentTimeElements?.forEach((element) => {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
addLiveIndicator(element);
|
|
1775
|
+
if (status.isLive) {
|
|
1776
|
+
updateLiveIndicator(element, status);
|
|
796
1777
|
} else {
|
|
797
1778
|
removeLiveIndicator(element);
|
|
798
1779
|
}
|
|
799
1780
|
});
|
|
800
1781
|
};
|
|
801
1782
|
checkForLiveContent();
|
|
1783
|
+
intervalRef.current = setInterval(checkForLiveContent, 1e3);
|
|
802
1784
|
observerRef.current = new MutationObserver((mutations) => {
|
|
803
1785
|
let shouldCheck = false;
|
|
804
1786
|
mutations.forEach((mutation) => {
|
|
@@ -824,31 +1806,289 @@ var useLiveIndicator = (containerRef, options = {}) => {
|
|
|
824
1806
|
characterData: true,
|
|
825
1807
|
characterDataOldValue: true
|
|
826
1808
|
});
|
|
827
|
-
const intervalId = setInterval(checkForLiveContent, 1e3);
|
|
828
1809
|
return () => {
|
|
829
1810
|
if (observerRef.current) {
|
|
830
1811
|
observerRef.current.disconnect();
|
|
831
1812
|
}
|
|
832
|
-
|
|
1813
|
+
if (intervalRef.current) {
|
|
1814
|
+
clearInterval(intervalRef.current);
|
|
1815
|
+
}
|
|
833
1816
|
};
|
|
834
|
-
}, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
|
|
1817
|
+
}, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
|
|
835
1818
|
return {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1819
|
+
seekToLiveEdge,
|
|
1820
|
+
getLiveStatus: () => getLiveStatus(playerRef.current)
|
|
1821
|
+
};
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
// src/hooks/useKeyboardControls.ts
|
|
1825
|
+
var import_react10 = require("react");
|
|
1826
|
+
var useKeyboardControls = (videoRef, options = {}) => {
|
|
1827
|
+
const { skipBack, skipForward, enabled = true } = options;
|
|
1828
|
+
const isDesktop = (0, import_react10.useCallback)(() => {
|
|
1829
|
+
return window.innerWidth > 767 && !/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
1830
|
+
}, []);
|
|
1831
|
+
const handleKeydown = (0, import_react10.useCallback)((event) => {
|
|
1832
|
+
if (!enabled || !isDesktop() || !videoRef.current) return;
|
|
1833
|
+
const activeElement = document.activeElement;
|
|
1834
|
+
if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)) {
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
switch (event.key) {
|
|
1838
|
+
case "ArrowLeft":
|
|
1839
|
+
event.preventDefault();
|
|
1840
|
+
skipBack?.();
|
|
1841
|
+
break;
|
|
1842
|
+
case "ArrowRight":
|
|
1843
|
+
event.preventDefault();
|
|
1844
|
+
skipForward?.();
|
|
1845
|
+
break;
|
|
1846
|
+
case " ":
|
|
1847
|
+
case "Space":
|
|
1848
|
+
event.preventDefault();
|
|
1849
|
+
if (videoRef.current.paused) {
|
|
1850
|
+
videoRef.current.play();
|
|
1851
|
+
} else {
|
|
1852
|
+
videoRef.current.pause();
|
|
1853
|
+
}
|
|
1854
|
+
break;
|
|
1855
|
+
}
|
|
1856
|
+
}, [enabled, videoRef, skipBack, skipForward, isDesktop]);
|
|
1857
|
+
(0, import_react10.useEffect)(() => {
|
|
1858
|
+
if (!enabled || !isDesktop()) return;
|
|
1859
|
+
document.addEventListener("keydown", handleKeydown);
|
|
1860
|
+
return () => {
|
|
1861
|
+
document.removeEventListener("keydown", handleKeydown);
|
|
1862
|
+
};
|
|
1863
|
+
}, [handleKeydown, enabled, isDesktop]);
|
|
1864
|
+
return {
|
|
1865
|
+
isDesktop: isDesktop()
|
|
1866
|
+
};
|
|
1867
|
+
};
|
|
1868
|
+
|
|
1869
|
+
// src/hooks/useAdEvents.ts
|
|
1870
|
+
var import_react11 = require("react");
|
|
1871
|
+
var useAdEvents = (playerRef, handlers) => {
|
|
1872
|
+
const listenersRef = (0, import_react11.useRef)([]);
|
|
1873
|
+
const setupAdEventListeners = (0, import_react11.useCallback)(() => {
|
|
1874
|
+
const player = playerRef.current;
|
|
1875
|
+
if (!player) return;
|
|
1876
|
+
const adManager = player.getAdManager();
|
|
1877
|
+
if (!adManager) return;
|
|
1878
|
+
const onAdsManagerLoaded = (event) => {
|
|
1879
|
+
const adsManager = event.getAdsManager();
|
|
1880
|
+
const onAdStarted = () => {
|
|
1881
|
+
console.log("Ad started");
|
|
1882
|
+
handlers.onAdStart?.();
|
|
1883
|
+
};
|
|
1884
|
+
const onAdComplete = () => {
|
|
1885
|
+
console.log("Ad completed");
|
|
1886
|
+
handlers.onAdComplete?.();
|
|
1887
|
+
};
|
|
1888
|
+
const onAdError = (adErrorEvent) => {
|
|
1889
|
+
console.error("Ad error:", adErrorEvent.getError());
|
|
1890
|
+
handlers.onAdError?.(adErrorEvent.getError());
|
|
1891
|
+
};
|
|
1892
|
+
const onAdSkipped = () => {
|
|
1893
|
+
console.log("Ad skipped");
|
|
1894
|
+
handlers.onAdSkipped?.();
|
|
1895
|
+
};
|
|
1896
|
+
const onAdPaused = () => {
|
|
1897
|
+
console.log("Ad paused");
|
|
1898
|
+
handlers.onAdPaused?.();
|
|
1899
|
+
};
|
|
1900
|
+
const onAdResumed = () => {
|
|
1901
|
+
console.log("Ad resumed");
|
|
1902
|
+
handlers.onAdResumed?.();
|
|
1903
|
+
};
|
|
1904
|
+
const onAdProgress = (adProgressData) => {
|
|
1905
|
+
handlers.onAdProgress?.(adProgressData);
|
|
1906
|
+
};
|
|
1907
|
+
const onAllAdsCompleted = () => {
|
|
1908
|
+
console.log("All ads completed");
|
|
1909
|
+
handlers.onAllAdsCompleted?.();
|
|
1910
|
+
};
|
|
1911
|
+
const adEventListeners = [];
|
|
1912
|
+
if (window.google?.ima) {
|
|
1913
|
+
const AdEvent = window.google.ima.AdEvent.Type;
|
|
1914
|
+
const AdErrorEvent = window.google.ima.AdErrorEvent.Type;
|
|
1915
|
+
if (handlers.onAdStart) {
|
|
1916
|
+
adsManager.addEventListener(AdEvent.STARTED, onAdStarted);
|
|
1917
|
+
adEventListeners.push({ event: AdEvent.STARTED, listener: onAdStarted });
|
|
1918
|
+
}
|
|
1919
|
+
if (handlers.onAdComplete) {
|
|
1920
|
+
adsManager.addEventListener(AdEvent.COMPLETE, onAdComplete);
|
|
1921
|
+
adEventListeners.push({ event: AdEvent.COMPLETE, listener: onAdComplete });
|
|
1922
|
+
}
|
|
1923
|
+
if (handlers.onAdError) {
|
|
1924
|
+
adsManager.addEventListener(AdErrorEvent.AD_ERROR, onAdError);
|
|
1925
|
+
adEventListeners.push({ event: AdErrorEvent.AD_ERROR, listener: onAdError });
|
|
1926
|
+
}
|
|
1927
|
+
if (handlers.onAdSkipped) {
|
|
1928
|
+
adsManager.addEventListener(AdEvent.SKIPPED, onAdSkipped);
|
|
1929
|
+
adEventListeners.push({ event: AdEvent.SKIPPED, listener: onAdSkipped });
|
|
1930
|
+
}
|
|
1931
|
+
if (handlers.onAdPaused) {
|
|
1932
|
+
adsManager.addEventListener(AdEvent.PAUSED, onAdPaused);
|
|
1933
|
+
adEventListeners.push({ event: AdEvent.PAUSED, listener: onAdPaused });
|
|
1934
|
+
}
|
|
1935
|
+
if (handlers.onAdResumed) {
|
|
1936
|
+
adsManager.addEventListener(AdEvent.RESUMED, onAdResumed);
|
|
1937
|
+
adEventListeners.push({ event: AdEvent.RESUMED, listener: onAdResumed });
|
|
1938
|
+
}
|
|
1939
|
+
if (handlers.onAdProgress) {
|
|
1940
|
+
adsManager.addEventListener(AdEvent.AD_PROGRESS, onAdProgress);
|
|
1941
|
+
adEventListeners.push({ event: AdEvent.AD_PROGRESS, listener: onAdProgress });
|
|
1942
|
+
}
|
|
1943
|
+
if (handlers.onAllAdsCompleted) {
|
|
1944
|
+
adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, onAllAdsCompleted);
|
|
1945
|
+
adEventListeners.push({ event: AdEvent.ALL_ADS_COMPLETED, listener: onAllAdsCompleted });
|
|
1946
|
+
}
|
|
1947
|
+
listenersRef.current.push({
|
|
1948
|
+
adsManager,
|
|
1949
|
+
listeners: adEventListeners
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
try {
|
|
1954
|
+
player.addEventListener("ad-started", () => {
|
|
1955
|
+
console.log("Shaka ad-started event");
|
|
1956
|
+
handlers.onAdStart?.();
|
|
1957
|
+
});
|
|
1958
|
+
player.addEventListener("ad-complete", () => {
|
|
1959
|
+
console.log("Shaka ad-complete event");
|
|
1960
|
+
handlers.onAdComplete?.();
|
|
1961
|
+
});
|
|
1962
|
+
player.addEventListener("ad-skipped", () => {
|
|
1963
|
+
console.log("Shaka ad-skipped event");
|
|
1964
|
+
handlers.onAdSkipped?.();
|
|
1965
|
+
});
|
|
1966
|
+
player.addEventListener("ad-error", (event) => {
|
|
1967
|
+
console.error("Shaka ad-error event:", event);
|
|
1968
|
+
handlers.onAdError?.(event);
|
|
1969
|
+
});
|
|
1970
|
+
listenersRef.current.push({
|
|
1971
|
+
type: "shaka",
|
|
1972
|
+
player,
|
|
1973
|
+
events: ["ad-started", "ad-complete", "ad-skipped", "ad-error"]
|
|
1974
|
+
});
|
|
1975
|
+
} catch (error) {
|
|
1976
|
+
console.warn("Error setting up ad event listeners:", error);
|
|
1977
|
+
}
|
|
1978
|
+
}, [playerRef, handlers]);
|
|
1979
|
+
const cleanupAdEventListeners = (0, import_react11.useCallback)(() => {
|
|
1980
|
+
try {
|
|
1981
|
+
listenersRef.current.forEach((listenerGroup) => {
|
|
1982
|
+
if (listenerGroup.type === "shaka" && listenerGroup.player) {
|
|
1983
|
+
listenerGroup.events.forEach((eventName) => {
|
|
1984
|
+
try {
|
|
1985
|
+
listenerGroup.player.removeEventListener(eventName, () => {
|
|
1986
|
+
});
|
|
1987
|
+
} catch (e) {
|
|
1988
|
+
console.warn(`Error removing ${eventName} listener:`, e);
|
|
1989
|
+
}
|
|
1990
|
+
});
|
|
1991
|
+
} else if (listenerGroup.adsManager && listenerGroup.listeners) {
|
|
1992
|
+
listenerGroup.listeners.forEach(({ event, listener }) => {
|
|
1993
|
+
try {
|
|
1994
|
+
listenerGroup.adsManager.removeEventListener(event, listener);
|
|
1995
|
+
} catch (e) {
|
|
1996
|
+
console.warn("Error removing ad listener:", e);
|
|
1997
|
+
}
|
|
1998
|
+
});
|
|
842
1999
|
}
|
|
843
2000
|
});
|
|
2001
|
+
listenersRef.current = [];
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
console.warn("Error cleaning up ad event listeners:", error);
|
|
844
2004
|
}
|
|
2005
|
+
}, []);
|
|
2006
|
+
return {
|
|
2007
|
+
setupAdEventListeners,
|
|
2008
|
+
cleanupAdEventListeners
|
|
845
2009
|
};
|
|
846
2010
|
};
|
|
847
2011
|
|
|
2012
|
+
// src/Player.tsx
|
|
2013
|
+
var import_tailwind_merge2 = require("tailwind-merge");
|
|
2014
|
+
|
|
2015
|
+
// src/utils/scriptLoader.ts
|
|
2016
|
+
var SCRIPT_CONFIGS = {
|
|
2017
|
+
ima: {
|
|
2018
|
+
src: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
|
|
2019
|
+
id: "ima-sdk",
|
|
2020
|
+
type: "text/javascript"
|
|
2021
|
+
},
|
|
2022
|
+
system73: {
|
|
2023
|
+
src: "//cdn.s73cloud.com/4/s73-sdk-shakaplayer.js",
|
|
2024
|
+
id: "system73-sdk",
|
|
2025
|
+
type: "application/javascript"
|
|
2026
|
+
}
|
|
2027
|
+
};
|
|
2028
|
+
function loadScript(config) {
|
|
2029
|
+
return new Promise((resolve, reject) => {
|
|
2030
|
+
if (document.getElementById(config.id)) {
|
|
2031
|
+
resolve();
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
const script = document.createElement("script");
|
|
2035
|
+
script.id = config.id;
|
|
2036
|
+
script.src = config.src;
|
|
2037
|
+
script.type = config.type || "text/javascript";
|
|
2038
|
+
script.async = true;
|
|
2039
|
+
script.onload = () => resolve();
|
|
2040
|
+
script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
|
|
2041
|
+
document.head.appendChild(script);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
function getRequiredScriptLoaders(needsIma, needsSystem73) {
|
|
2045
|
+
const loaders = [];
|
|
2046
|
+
if (needsIma) {
|
|
2047
|
+
loaders.push(loadScript(SCRIPT_CONFIGS.ima));
|
|
2048
|
+
}
|
|
2049
|
+
if (needsSystem73) {
|
|
2050
|
+
loaders.push(loadScript(SCRIPT_CONFIGS.system73));
|
|
2051
|
+
}
|
|
2052
|
+
return loaders;
|
|
2053
|
+
}
|
|
2054
|
+
async function loadScripts(scriptLoaders) {
|
|
2055
|
+
if (scriptLoaders.length === 0) {
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
2058
|
+
try {
|
|
2059
|
+
await Promise.all(scriptLoaders);
|
|
2060
|
+
} catch (error) {
|
|
2061
|
+
console.error("Error loading scripts:", error);
|
|
2062
|
+
throw error;
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
function waitForGlobal(globalName, timeout = 5e3) {
|
|
2066
|
+
return new Promise((resolve, reject) => {
|
|
2067
|
+
const startTime = Date.now();
|
|
2068
|
+
function checkGlobal() {
|
|
2069
|
+
const global = window[globalName];
|
|
2070
|
+
if (global) {
|
|
2071
|
+
resolve(global);
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
if (Date.now() - startTime > timeout) {
|
|
2075
|
+
reject(new Error(`Timeout waiting for global: ${globalName}`));
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
setTimeout(checkGlobal, 100);
|
|
2079
|
+
}
|
|
2080
|
+
checkGlobal();
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2083
|
+
async function waitForGlobals(globalNames, timeout = 5e3) {
|
|
2084
|
+
const promises = globalNames.map((name) => waitForGlobal(name, timeout));
|
|
2085
|
+
await Promise.all(promises);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
848
2088
|
// src/components/Loading.tsx
|
|
849
2089
|
var import_tailwind_merge = require("tailwind-merge");
|
|
850
|
-
var
|
|
851
|
-
var Loading = ({ className }) => /* @__PURE__ */ (0,
|
|
2090
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2091
|
+
var Loading = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
852
2092
|
"div",
|
|
853
2093
|
{
|
|
854
2094
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -856,17 +2096,36 @@ var Loading = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
|
856
2096
|
className
|
|
857
2097
|
),
|
|
858
2098
|
role: "status",
|
|
859
|
-
children:
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
2099
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: " flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2100
|
+
"svg",
|
|
2101
|
+
{
|
|
2102
|
+
className: "shaka-spinner-svg animate-spin h-12 w-12",
|
|
2103
|
+
viewBox: "0 0 64 64",
|
|
2104
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2105
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2106
|
+
"circle",
|
|
2107
|
+
{
|
|
2108
|
+
className: "shaka-spinner-path",
|
|
2109
|
+
cx: "32",
|
|
2110
|
+
cy: "32",
|
|
2111
|
+
r: "28",
|
|
2112
|
+
strokeWidth: "4",
|
|
2113
|
+
strokeLinecap: "round",
|
|
2114
|
+
stroke: "currentColor",
|
|
2115
|
+
fill: "none",
|
|
2116
|
+
strokeDasharray: "176",
|
|
2117
|
+
strokeDashoffset: "120"
|
|
2118
|
+
}
|
|
2119
|
+
)
|
|
2120
|
+
}
|
|
2121
|
+
) })
|
|
863
2122
|
}
|
|
864
2123
|
);
|
|
865
2124
|
|
|
866
2125
|
// src/components/ErrorScreen.tsx
|
|
867
|
-
var
|
|
868
|
-
var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0,
|
|
869
|
-
/* @__PURE__ */ (0,
|
|
2126
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2127
|
+
var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-full h-full md:rounded-2xl! aspect-video bg-black flex", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "bg-[#151515] text-white w-full h-full flex justify-center items-center", children: [
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
870
2129
|
"svg",
|
|
871
2130
|
{
|
|
872
2131
|
className: "w-24 h-24 m-6",
|
|
@@ -876,7 +2135,7 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0, import_jsx_run
|
|
|
876
2135
|
style: { width: 96 },
|
|
877
2136
|
viewBox: "0 0 24 24",
|
|
878
2137
|
xmlns: "http://www.w3.org/2000/svg",
|
|
879
|
-
children: /* @__PURE__ */ (0,
|
|
2138
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
880
2139
|
"path",
|
|
881
2140
|
{
|
|
882
2141
|
d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z",
|
|
@@ -886,66 +2145,22 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0, import_jsx_run
|
|
|
886
2145
|
)
|
|
887
2146
|
}
|
|
888
2147
|
),
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
2148
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
2149
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
|
|
892
2151
|
] })
|
|
893
2152
|
] }) });
|
|
894
2153
|
|
|
895
2154
|
// src/components/Title.tsx
|
|
896
|
-
var
|
|
897
|
-
var Title = ({ title }) => /* @__PURE__ */ (0,
|
|
898
|
-
|
|
899
|
-
// src/components/LiveBadge.tsx
|
|
900
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
901
|
-
var LiveBadge = ({
|
|
902
|
-
isVisible,
|
|
903
|
-
position = "top-right",
|
|
904
|
-
className = "",
|
|
905
|
-
style = {},
|
|
906
|
-
text = "LIVE"
|
|
907
|
-
}) => {
|
|
908
|
-
if (!isVisible) return null;
|
|
909
|
-
const positionClasses = {
|
|
910
|
-
"top-left": "top-4 left-4",
|
|
911
|
-
"top-right": "top-4 right-4",
|
|
912
|
-
"bottom-left": "bottom-4 left-4",
|
|
913
|
-
"bottom-right": "bottom-4 right-4"
|
|
914
|
-
};
|
|
915
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
916
|
-
"div",
|
|
917
|
-
{
|
|
918
|
-
className: `
|
|
919
|
-
absolute z-50
|
|
920
|
-
${positionClasses[position]}
|
|
921
|
-
bg-red-600 text-white
|
|
922
|
-
px-2 py-1
|
|
923
|
-
rounded-md
|
|
924
|
-
text-xs font-bold
|
|
925
|
-
uppercase tracking-wide
|
|
926
|
-
shadow-lg
|
|
927
|
-
animate-pulse
|
|
928
|
-
pointer-events-none
|
|
929
|
-
${className}
|
|
930
|
-
`,
|
|
931
|
-
style,
|
|
932
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "flex items-center gap-1", children: [
|
|
933
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-2 h-2 bg-white rounded-full animate-pulse" }),
|
|
934
|
-
text
|
|
935
|
-
] })
|
|
936
|
-
}
|
|
937
|
-
);
|
|
938
|
-
};
|
|
939
|
-
|
|
940
|
-
// src/styles.css
|
|
941
|
-
styleInject('/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --tracking-wide: 0.025em;\n --tracking-widest: 0.1em;\n --radius-md: 0.375rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --aspect-video: 16 / 9;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-auto {\n pointer-events: auto;\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .visible {\n visibility: visible;\n }\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .z-10 {\n z-index: 10;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-6 {\n margin: calc(var(--spacing) * 6);\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-3 {\n margin-top: calc(var(--spacing) * 3);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .aspect-video {\n aspect-ratio: var(--aspect-video);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-8 {\n height: calc(var(--spacing) * 8);\n }\n .h-24 {\n height: calc(var(--spacing) * 24);\n }\n .h-full {\n height: 100%;\n }\n .w-2 {\n width: calc(var(--spacing) * 2);\n }\n .w-8 {\n width: calc(var(--spacing) * 8);\n }\n .w-24 {\n width: calc(var(--spacing) * 24);\n }\n .w-full {\n width: 100%;\n }\n .animate-pulse {\n animation: var(--animate-pulse);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .auto-cols-max {\n grid-auto-columns: max-content;\n }\n .grid-flow-col {\n grid-auto-flow: column;\n }\n .flex-col {\n flex-direction: column;\n }\n .items-center {\n align-items: center;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-stretch {\n justify-content: stretch;\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-5 {\n gap: calc(var(--spacing) * 5);\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-white {\n border-color: var(--color-white);\n }\n .bg-\\[\\#151515\\] {\n background-color: #151515;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-red-600 {\n background-color: var(--color-red-600);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-t {\n --tw-gradient-position: to top in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-black\\/70 {\n --tw-gradient-from: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-gradient-from: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-transparent {\n --tw-gradient-to: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .font-mono {\n font-family: var(--font-mono);\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-5xl {\n font-size: var(--text-5xl);\n line-height: var(--tw-leading, var(--text-5xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .tracking-wide {\n --tw-tracking: var(--tracking-wide);\n letter-spacing: var(--tracking-wide);\n }\n .tracking-widest {\n --tw-tracking: var(--tracking-widest);\n letter-spacing: var(--tracking-widest);\n }\n .text-white {\n color: var(--color-white);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .md\\:rounded-2xl {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl);\n }\n }\n .md\\:rounded-2xl\\! {\n @media (width >= 48rem) {\n border-radius: var(--radius-2xl) !important;\n }\n }\n .md\\:text-base {\n @media (width >= 48rem) {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n }\n .md\\:text-sm {\n @media (width >= 48rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:text-xl {\n @media (width >= 48rem) {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n }\n}\n@layer components {\n .motto-video-container {\n position: relative;\n width: 100%;\n min-height: 300px;\n }\n @supports (aspect-ratio: 16/9) {\n .motto-video-container {\n min-height: auto;\n }\n }\n .motto-video-responsive {\n position: absolute;\n top: calc(var(--spacing) * 0);\n left: calc(var(--spacing) * 0);\n height: 100%;\n width: 100%;\n }\n .motto-skip-button {\n position: absolute;\n top: calc(1/2 * 100%);\n z-index: 10;\n display: flex;\n height: calc(var(--spacing) * 16);\n width: calc(var(--spacing) * 16);\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 70%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 70%, transparent);\n }\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n color: var(--color-white);\n opacity: 80%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n &:hover {\n @media (hover: hover) {\n --tw-scale-x: 110%;\n --tw-scale-y: 110%;\n --tw-scale-z: 110%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n &:hover {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .motto-skip-button-back {\n left: calc(var(--spacing) * 5);\n }\n .motto-skip-button-forward {\n right: calc(var(--spacing) * 5);\n }\n .motto-mobile-controls-overlay {\n position: absolute;\n inset: calc(var(--spacing) * 0);\n z-index: 20;\n display: flex;\n align-items: center;\n justify-content: center;\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 300ms;\n transition-duration: 300ms;\n pointer-events: none;\n }\n .motto-mobile-controls-group {\n display: flex;\n align-items: center;\n gap: calc(var(--spacing) * 8);\n opacity: 100%;\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: none;\n }\n .motto-mobile-play-button {\n display: flex;\n height: calc(var(--spacing) * 14);\n width: calc(var(--spacing) * 14);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-play-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-play-button svg {\n height: calc(var(--spacing) * 7);\n width: calc(var(--spacing) * 7);\n }\n .motto-mobile-skip-button {\n display: flex;\n height: calc(var(--spacing) * 10);\n width: calc(var(--spacing) * 10);\n cursor: pointer;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n border-radius: calc(infinity * 1px);\n border-style: var(--tw-border-style);\n border-width: 0px;\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n color: var(--color-white);\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n --tw-duration: 200ms;\n transition-duration: 200ms;\n pointer-events: auto;\n }\n .motto-mobile-skip-button:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n .motto-mobile-skip-button svg {\n height: calc(var(--spacing) * 6);\n width: calc(var(--spacing) * 6);\n }\n}\n@media (min-width: 768px) {\n .motto-mobile-controls-overlay {\n display: none !important;\n }\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-button[title*="Skip back"],\n .shaka-controls-container .shaka-button[title*="Skip forward"],\n .shaka-controls-container .shaka-button[aria-label*="Skip back"],\n .shaka-controls-container .shaka-button[aria-label*="Skip forward"],\n .shaka-controls-container button[title*="Skip back"],\n .shaka-controls-container button[title*="Skip forward"],\n .shaka-controls-container button[aria-label*="Skip back"],\n .shaka-controls-container button[aria-label*="Skip forward"],\n .motto-native-skip-button:not(.motto-mobile-skip-button),\n .motto-skip-back-button:not(.motto-mobile-skip-button),\n .motto-skip-forward-button:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n .shaka-button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button),\n button[title*="Skip back"]:not(.motto-mobile-skip-button),\n button[title*="Skip forward"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip back"]:not(.motto-mobile-skip-button),\n button[aria-label*="Skip forward"]:not(.motto-mobile-skip-button) {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n width: 0 !important;\n height: 0 !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n .motto-mobile-skip-button {\n display: flex !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n}\n.shaka-seek-bar-container {\n height: 6px !important;\n width: 100% !important;\n margin: 8px 0 !important;\n border-radius: 4px !important;\n position: relative !important;\n border-top: none !important;\n border-bottom: none !important;\n box-shadow: none !important;\n}\n.shaka-seek-bar {\n height: 6px !important;\n width: 100% !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n background: transparent !important;\n cursor: pointer !important;\n border: none !important;\n outline: none !important;\n position: absolute !important;\n top: 0 !important;\n left: 0 !important;\n border-radius: 4px !important;\n}\n.shaka-seek-bar::-webkit-slider-runnable-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-moz-range-track {\n height: 6px !important;\n background: transparent !important;\n border-radius: 4px !important;\n border: none !important;\n}\n.shaka-seek-bar::-webkit-slider-thumb {\n -webkit-appearance: none !important;\n appearance: none !important;\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.shaka-seek-bar::-moz-range-thumb {\n width: 16px !important;\n height: 16px !important;\n border-radius: 50% !important;\n background: #ffffff !important;\n cursor: pointer !important;\n border: 2px solid #ffffff !important;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) !important;\n margin-top: -4px !important;\n}\n.motto-skip-back-button,\n.motto-skip-forward-button,\n.motto-native-skip-button {\n background: transparent !important;\n border: none !important;\n padding: 4px !important;\n margin: 0px !important;\n cursor: pointer !important;\n color: #ffffff !important;\n transition: all 0.2s ease !important;\n min-width: 32px !important;\n height: 32px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n border-radius: 4px !important;\n width: 25px;\n}\n.motto-skip-back-button:hover,\n.motto-skip-forward-button:hover,\n.motto-native-skip-button:hover {\n opacity: 0.8 !important;\n background: transparent !important;\n transform: scale(1.05) !important;\n}\n.motto-skip-back-button:active,\n.motto-skip-forward-button:active,\n.motto-native-skip-button:active {\n transform: scale(0.95) !important;\n}\n.motto-skip-back-button svg,\n.motto-skip-forward-button svg,\n.motto-native-skip-button svg {\n width: 24px !important;\n height: 24px !important;\n}\n@media (max-width: 767px) {\n .shaka-controls-container .motto-native-skip-button,\n .shaka-controls-container .motto-skip-back-button,\n .shaka-controls-container .motto-skip-forward-button,\n .shaka-controls-container .shaka-play-button,\n .shaka-controls-container .shaka-pause-button {\n display: none !important;\n }\n}\n.shaka-spinner-svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-spinner-path {\n stroke: white !important;\n fill: none !important;\n}\n.shaka-spinner-container {\n color: white !important;\n}\n.shaka-buffering-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-buffering-spinner path {\n stroke: white !important;\n fill: none !important;\n}\n[data-shaka-player-container] .shaka-spinner,\n[data-shaka-player-container] .spinner {\n color: white !important;\n border-color: white !important;\n}\n.material-icons.shaka-spinner {\n color: white !important;\n}\n.shaka-controls-container .shaka-spinner,\n.shaka-video-container .shaka-spinner {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner svg,\n.shaka-video-container .shaka-spinner svg {\n color: white !important;\n fill: white !important;\n}\n.shaka-controls-container .shaka-spinner path,\n.shaka-video-container .shaka-spinner path {\n stroke: white !important;\n}\n.motto-video-loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n linear-gradient(\n 135deg,\n #1a1a1a 0%,\n #2d2d2d 100%);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: opacity 0.3s ease;\n}\n.motto-video-loading-overlay.hidden {\n opacity: 0;\n pointer-events: none;\n}\n.motto-video-loading-content {\n text-align: center;\n color: white;\n}\n.motto-video-loading-icon {\n width: 64px;\n height: 64px;\n margin-bottom: 16px;\n opacity: 0.7;\n}\n.motto-video-loading-text {\n font-size: 16px;\n font-weight: 500;\n margin-bottom: 8px;\n}\n.motto-video-loading-subtext {\n font-size: 14px;\n opacity: 0.7;\n}\n@keyframes pulse-live {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.7;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-tracking { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-translate-x { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-y { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-translate-z { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-font-weight: initial;\n --tw-tracking: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
|
|
2155
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2156
|
+
var Title = ({ title }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "text-white text-xl font-semibold", children: title }) });
|
|
942
2157
|
|
|
943
2158
|
// src/Player.tsx
|
|
944
|
-
var
|
|
945
|
-
var
|
|
946
|
-
var Player = (0, import_react10.forwardRef)(
|
|
2159
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2160
|
+
var Player = (0, import_react12.forwardRef)(
|
|
947
2161
|
({
|
|
948
2162
|
src,
|
|
2163
|
+
managedMode = false,
|
|
949
2164
|
autoPlay = false,
|
|
950
2165
|
loop = false,
|
|
951
2166
|
muted = false,
|
|
@@ -957,25 +2172,48 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
957
2172
|
shakaConfig,
|
|
958
2173
|
drmConfig,
|
|
959
2174
|
muxConfig,
|
|
2175
|
+
system73Config,
|
|
960
2176
|
imaConfig,
|
|
961
2177
|
chromecastConfig,
|
|
962
2178
|
qualityConfig,
|
|
963
2179
|
seekbarConfig,
|
|
2180
|
+
iconSizes,
|
|
964
2181
|
events,
|
|
2182
|
+
locale = "en",
|
|
965
2183
|
containerClassName,
|
|
966
|
-
|
|
2184
|
+
liveThresholdSeconds = 15,
|
|
2185
|
+
publicKey,
|
|
2186
|
+
auth,
|
|
2187
|
+
...videoProps
|
|
967
2188
|
}, ref) => {
|
|
968
|
-
const videoRef = (0,
|
|
969
|
-
const containerRef = (0,
|
|
970
|
-
const
|
|
971
|
-
(0,
|
|
972
|
-
const
|
|
2189
|
+
const videoRef = (0, import_react12.useRef)(null);
|
|
2190
|
+
const containerRef = (0, import_react12.useRef)(null);
|
|
2191
|
+
const [isScriptsLoaded, setIsScriptsLoaded] = (0, import_react12.useState)(false);
|
|
2192
|
+
const [isInitialLoading, setIsInitialLoading] = (0, import_react12.useState)(true);
|
|
2193
|
+
const [bfResetKey, setBfResetKey] = (0, import_react12.useState)(0);
|
|
2194
|
+
const hasPlaylist = !!src && (typeof src === "string" || !!(src.url || src.drm?.widevine?.playlistUrl || src.drm?.playready?.playlistUrl || src.drm?.fairplay?.playlistUrl));
|
|
2195
|
+
(0, import_react12.useImperativeHandle)(ref, () => videoRef.current, []);
|
|
2196
|
+
const { playerRef, initializePlayer, loadManifest, destroyPlayer, isRetrying } = useShakaPlayer({
|
|
973
2197
|
src,
|
|
974
2198
|
shakaConfig,
|
|
975
2199
|
drmConfig,
|
|
976
2200
|
onError: events?.onError,
|
|
977
|
-
onPlayerReady: events?.onPlayerReady
|
|
2201
|
+
onPlayerReady: events?.onPlayerReady,
|
|
2202
|
+
muxConfig,
|
|
2203
|
+
onMuxReady: events?.onMuxReady,
|
|
2204
|
+
onMuxDataUpdate: events?.onMuxDataUpdate,
|
|
2205
|
+
publicKey,
|
|
2206
|
+
mottoToken: auth?.mottoToken,
|
|
2207
|
+
hasAds: !!imaConfig?.adTagUrl,
|
|
2208
|
+
hasSystem73: !!system73Config?.apiKey,
|
|
2209
|
+
apiToken: auth?.apiToken
|
|
978
2210
|
});
|
|
2211
|
+
const {
|
|
2212
|
+
initializeMux,
|
|
2213
|
+
updateMuxData,
|
|
2214
|
+
handleMuxError,
|
|
2215
|
+
destroyMux
|
|
2216
|
+
} = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
|
|
979
2217
|
const {
|
|
980
2218
|
getAvailableQualities,
|
|
981
2219
|
setQuality,
|
|
@@ -988,12 +2226,11 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
988
2226
|
skipDuration,
|
|
989
2227
|
shouldShowSkipControls
|
|
990
2228
|
} = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
} = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
|
|
2229
|
+
useKeyboardControls(videoRef, {
|
|
2230
|
+
skipBack,
|
|
2231
|
+
skipForward,
|
|
2232
|
+
enabled: true
|
|
2233
|
+
});
|
|
997
2234
|
const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
|
|
998
2235
|
onPlay: events?.onPlay,
|
|
999
2236
|
onPause: events?.onPause,
|
|
@@ -1009,110 +2246,231 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1009
2246
|
chromecastConfig,
|
|
1010
2247
|
seekbarConfig,
|
|
1011
2248
|
events?.onSkipBack,
|
|
1012
|
-
events?.onSkipForward
|
|
2249
|
+
events?.onSkipForward,
|
|
2250
|
+
iconSizes,
|
|
2251
|
+
locale
|
|
1013
2252
|
);
|
|
1014
|
-
const {
|
|
1015
|
-
enabled: true,
|
|
1016
|
-
onLiveStateChange: (isLive2) => {
|
|
1017
|
-
events?.onLiveStateChange?.(isLive2);
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
useLiveIndicator(containerRef, {
|
|
2253
|
+
const { getLiveStatus, seekToLiveEdge } = useLiveIndicator(containerRef, playerRef, {
|
|
1021
2254
|
enabled: true,
|
|
1022
2255
|
indicatorColor: "#ff0000",
|
|
1023
2256
|
indicatorSize: 8,
|
|
1024
|
-
showPulseAnimation: true
|
|
2257
|
+
showPulseAnimation: true,
|
|
2258
|
+
liveThresholdSeconds,
|
|
2259
|
+
onLiveStatusChange: events?.onLiveStatusChange
|
|
1025
2260
|
});
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
if (imaConfig.adTagUrl) {
|
|
1040
|
-
const adContainer = adContainerRef.current;
|
|
1041
|
-
if (adContainer) {
|
|
1042
|
-
adManager.initClientSide(adContainer, videoRef.current, imaConfig.adsRenderingSettings);
|
|
1043
|
-
const adsRequest = {
|
|
1044
|
-
adTagUrl: imaConfig.adTagUrl,
|
|
1045
|
-
linearAdSlotWidth: imaConfig.linearAdSlotWidth || width || 640,
|
|
1046
|
-
linearAdSlotHeight: imaConfig.linearAdSlotHeight || height || 360,
|
|
1047
|
-
nonLinearAdSlotWidth: imaConfig.nonLinearAdSlotWidth || width || 640,
|
|
1048
|
-
nonLinearAdSlotHeight: imaConfig.nonLinearAdSlotHeight || 150
|
|
1049
|
-
};
|
|
1050
|
-
adManager.requestClientSideAds(adsRequest);
|
|
1051
|
-
}
|
|
2261
|
+
const { setupAdEventListeners, cleanupAdEventListeners } = useAdEvents(playerRef, {
|
|
2262
|
+
onAdStart: events?.onAdStart,
|
|
2263
|
+
onAdComplete: events?.onAdComplete,
|
|
2264
|
+
onAdError: events?.onAdError,
|
|
2265
|
+
onAdSkipped: events?.onAdSkipped,
|
|
2266
|
+
onAdPaused: events?.onAdPaused,
|
|
2267
|
+
onAdResumed: events?.onAdResumed,
|
|
2268
|
+
onAdProgress: events?.onAdProgress,
|
|
2269
|
+
onAllAdsCompleted: events?.onAllAdsCompleted
|
|
2270
|
+
});
|
|
2271
|
+
const initializeSystem73 = (0, import_react12.useCallback)((playerConfig) => {
|
|
2272
|
+
if (!system73Config?.apiKey || !window.S73ShakaPlayerWrapper) {
|
|
2273
|
+
return null;
|
|
1052
2274
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
2275
|
+
console.log("Initializing System73 SDK...");
|
|
2276
|
+
try {
|
|
2277
|
+
const s73Config = {
|
|
2278
|
+
apiKey: system73Config.apiKey,
|
|
2279
|
+
contentSteeringEndpoint: system73Config.contentSteeringEndpoint,
|
|
2280
|
+
channelId: system73Config.channelId
|
|
2281
|
+
};
|
|
2282
|
+
const wrapper = window.S73ShakaPlayerWrapper(s73Config, { shaka: import_shaka_player4.default });
|
|
2283
|
+
wrapper.wrapPlayerConfig(playerConfig);
|
|
2284
|
+
console.log("System73 SDK initialized with config:", s73Config);
|
|
2285
|
+
return wrapper;
|
|
2286
|
+
} catch (error) {
|
|
2287
|
+
console.error("Error initializing System73 SDK:", error);
|
|
2288
|
+
return null;
|
|
2289
|
+
}
|
|
2290
|
+
}, [system73Config]);
|
|
2291
|
+
const initializeAds = (0, import_react12.useCallback)(async () => {
|
|
2292
|
+
if (!imaConfig?.adTagUrl || !playerRef.current || !videoRef.current || !uiRef.current) {
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
if (!window.google?.ima) {
|
|
2296
|
+
console.error("Google IMA SDK not available when trying to initialize ads");
|
|
1056
2297
|
return;
|
|
1057
2298
|
}
|
|
1058
2299
|
try {
|
|
1059
|
-
|
|
1060
|
-
|
|
2300
|
+
const player = playerRef.current;
|
|
2301
|
+
const video = videoRef.current;
|
|
2302
|
+
const ui = uiRef.current;
|
|
2303
|
+
const controls2 = ui.getControls();
|
|
2304
|
+
const container = controls2.getClientSideAdContainer();
|
|
2305
|
+
const adManager = player.getAdManager();
|
|
2306
|
+
if (!adManager) {
|
|
2307
|
+
console.error("Ad manager not available");
|
|
2308
|
+
return;
|
|
1061
2309
|
}
|
|
2310
|
+
const google = window.google;
|
|
2311
|
+
let adsRenderingSettings = null;
|
|
2312
|
+
if (imaConfig.adsRenderingSettings) {
|
|
2313
|
+
adsRenderingSettings = imaConfig.adsRenderingSettings;
|
|
2314
|
+
} else if (autoPlay) {
|
|
2315
|
+
adsRenderingSettings = new google.ima.AdsRenderingSettings();
|
|
2316
|
+
adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
|
|
2317
|
+
}
|
|
2318
|
+
adManager.initClientSide(container, video, adsRenderingSettings);
|
|
2319
|
+
const adsRequest = new google.ima.AdsRequest();
|
|
2320
|
+
adsRequest.adTagUrl = imaConfig.adTagUrl;
|
|
2321
|
+
adManager.requestClientSideAds(adsRequest);
|
|
2322
|
+
setupAdEventListeners();
|
|
2323
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
2324
|
+
await loadManifest();
|
|
1062
2325
|
} catch (error) {
|
|
1063
|
-
console.
|
|
2326
|
+
console.error("Error initializing ads:", error);
|
|
1064
2327
|
}
|
|
1065
|
-
};
|
|
1066
|
-
(0,
|
|
2328
|
+
}, [imaConfig, autoPlay, setupAdEventListeners, loadManifest]);
|
|
2329
|
+
(0, import_react12.useEffect)(() => {
|
|
2330
|
+
const loadRequiredScripts = async () => {
|
|
2331
|
+
try {
|
|
2332
|
+
const scriptLoaders = getRequiredScriptLoaders(!!imaConfig?.adTagUrl, !!system73Config?.apiKey);
|
|
2333
|
+
await loadScripts(scriptLoaders);
|
|
2334
|
+
const globalsToWait = [];
|
|
2335
|
+
if (imaConfig?.adTagUrl) {
|
|
2336
|
+
globalsToWait.push("google");
|
|
2337
|
+
}
|
|
2338
|
+
if (system73Config?.apiKey) {
|
|
2339
|
+
globalsToWait.push("S73ShakaPlayerWrapper");
|
|
2340
|
+
}
|
|
2341
|
+
if (globalsToWait.length > 0) {
|
|
2342
|
+
await waitForGlobals(globalsToWait);
|
|
2343
|
+
}
|
|
2344
|
+
setIsScriptsLoaded(true);
|
|
2345
|
+
} catch (error) {
|
|
2346
|
+
console.error("Error loading required scripts:", error);
|
|
2347
|
+
setIsScriptsLoaded(true);
|
|
2348
|
+
}
|
|
2349
|
+
};
|
|
2350
|
+
loadRequiredScripts();
|
|
2351
|
+
}, [imaConfig?.adTagUrl, system73Config?.apiKey]);
|
|
2352
|
+
(0, import_react12.useEffect)(() => {
|
|
2353
|
+
const onPageShow = (e) => {
|
|
2354
|
+
if (e && e.persisted) {
|
|
2355
|
+
setBfResetKey((k) => k + 1);
|
|
2356
|
+
}
|
|
2357
|
+
};
|
|
2358
|
+
window.addEventListener("pageshow", onPageShow);
|
|
2359
|
+
return () => window.removeEventListener("pageshow", onPageShow);
|
|
2360
|
+
}, []);
|
|
2361
|
+
(0, import_react12.useEffect)(() => {
|
|
1067
2362
|
const video = videoRef.current;
|
|
1068
|
-
if (!video) return;
|
|
2363
|
+
if (!video || !isScriptsLoaded) return;
|
|
1069
2364
|
const initialize = async () => {
|
|
1070
2365
|
try {
|
|
2366
|
+
console.log("\u{1F680} [Player] Starting initialization...");
|
|
2367
|
+
setIsInitialLoading(true);
|
|
2368
|
+
let system73Wrapper = null;
|
|
2369
|
+
if (system73Config?.apiKey && window.S73ShakaPlayerWrapper) {
|
|
2370
|
+
console.log("\u{1F4E6} [System73] Step 1: Initializing System73 wrapper with config");
|
|
2371
|
+
const playerConfig = { ...shakaConfig };
|
|
2372
|
+
system73Wrapper = initializeSystem73(playerConfig);
|
|
2373
|
+
if (system73Wrapper) {
|
|
2374
|
+
shakaConfig = playerConfig;
|
|
2375
|
+
console.log("\u2705 [System73] Step 1 complete: Wrapper created and config modified");
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
console.log("\u{1F3AC} [Shaka] Step 2: Initializing Shaka Player (auto-load:", !system73Config?.apiKey && !imaConfig?.adTagUrl, ")");
|
|
1071
2379
|
await initializePlayer(video);
|
|
2380
|
+
console.log("\u2705 [Shaka] Step 2 complete: Player initialized");
|
|
2381
|
+
if (system73Wrapper && playerRef.current) {
|
|
2382
|
+
console.log("\u{1F517} [System73] Step 3: Wrapping Shaka player with System73");
|
|
2383
|
+
system73Wrapper.wrapPlayer(playerRef.current);
|
|
2384
|
+
console.log("\u2705 [System73] Step 3 complete: Player wrapped");
|
|
2385
|
+
if (!imaConfig?.adTagUrl) {
|
|
2386
|
+
console.log("\u{1F4FA} [System73] Step 4: Loading manifest");
|
|
2387
|
+
await loadManifest();
|
|
2388
|
+
console.log("\u2705 [System73] Step 4 complete: Manifest loaded");
|
|
2389
|
+
} else {
|
|
2390
|
+
console.log("\u23ED\uFE0F [System73] Skipping manifest load - ads will handle it");
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
console.log("\u{1F4CB} [Player] Setting up event listeners and quality tracking");
|
|
1072
2394
|
setupEventListeners();
|
|
1073
2395
|
const cleanupQuality = setupQualityTracking();
|
|
1074
2396
|
configureQuality();
|
|
2397
|
+
console.log("\u{1F3A8} [UI] Initializing Shaka UI");
|
|
1075
2398
|
await initializeUI();
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
2399
|
+
console.log("\u2705 [UI] UI initialized");
|
|
2400
|
+
if (imaConfig?.adTagUrl && window.google?.ima) {
|
|
2401
|
+
console.log("\u{1F4E2} [Ads] Initializing ads (will load manifest after VAST fetch)");
|
|
2402
|
+
await initializeAds();
|
|
2403
|
+
console.log("\u2705 [Ads] Ads initialized and manifest loaded");
|
|
2404
|
+
}
|
|
2405
|
+
console.log("\u2728 [Player] Initialization complete!");
|
|
1079
2406
|
} catch (error) {
|
|
1080
|
-
console.error("Error during
|
|
2407
|
+
console.error("\u274C [Player] Error during initialization:", error);
|
|
1081
2408
|
handleMuxError(error);
|
|
1082
2409
|
}
|
|
1083
2410
|
};
|
|
1084
2411
|
initialize();
|
|
1085
2412
|
return () => {
|
|
1086
2413
|
cleanupEventListeners();
|
|
2414
|
+
cleanupAdEventListeners();
|
|
1087
2415
|
destroyUI();
|
|
1088
2416
|
destroyMux();
|
|
1089
2417
|
destroyPlayer();
|
|
1090
2418
|
};
|
|
1091
|
-
}, [
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
2419
|
+
}, [managedMode ? hasPlaylist : src, isScriptsLoaded, bfResetKey, managedMode]);
|
|
2420
|
+
(0, import_react12.useEffect)(() => {
|
|
2421
|
+
const video = videoRef.current;
|
|
2422
|
+
if (!video) return;
|
|
2423
|
+
const onLoadStart = () => {
|
|
2424
|
+
setIsInitialLoading(true);
|
|
2425
|
+
};
|
|
2426
|
+
const onCanPlay = () => {
|
|
2427
|
+
setIsInitialLoading(false);
|
|
2428
|
+
};
|
|
2429
|
+
const onPlaying = () => {
|
|
2430
|
+
setIsInitialLoading(false);
|
|
2431
|
+
};
|
|
2432
|
+
video.addEventListener("loadstart", onLoadStart);
|
|
2433
|
+
video.addEventListener("canplay", onCanPlay);
|
|
2434
|
+
video.addEventListener("playing", onPlaying);
|
|
2435
|
+
return () => {
|
|
2436
|
+
video.removeEventListener("loadstart", onLoadStart);
|
|
2437
|
+
video.removeEventListener("canplay", onCanPlay);
|
|
2438
|
+
video.removeEventListener("playing", onPlaying);
|
|
2439
|
+
};
|
|
2440
|
+
}, []);
|
|
2441
|
+
(0, import_react12.useEffect)(() => {
|
|
1107
2442
|
const video = videoRef.current;
|
|
1108
2443
|
if (!video) return;
|
|
1109
2444
|
video.autoplay = autoPlay;
|
|
1110
2445
|
video.loop = loop;
|
|
1111
|
-
video.muted = muted;
|
|
1112
2446
|
video.controls = false;
|
|
1113
2447
|
if (poster) video.poster = poster;
|
|
1114
|
-
}, [autoPlay, loop, muted, poster]);
|
|
1115
|
-
(0,
|
|
2448
|
+
}, [autoPlay, loop, muted, poster, imaConfig?.adTagUrl]);
|
|
2449
|
+
(0, import_react12.useEffect)(() => {
|
|
2450
|
+
const video = videoRef.current;
|
|
2451
|
+
if (!video) return;
|
|
2452
|
+
video.controls = false;
|
|
2453
|
+
video.setAttribute("controls", "false");
|
|
2454
|
+
video.removeAttribute("controls");
|
|
2455
|
+
const observer = new MutationObserver((mutations) => {
|
|
2456
|
+
mutations.forEach((mutation) => {
|
|
2457
|
+
if (mutation.type === "attributes" && mutation.attributeName === "controls") {
|
|
2458
|
+
if (video.hasAttribute("controls")) {
|
|
2459
|
+
video.removeAttribute("controls");
|
|
2460
|
+
video.controls = false;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
});
|
|
2464
|
+
});
|
|
2465
|
+
observer.observe(video, {
|
|
2466
|
+
attributes: true,
|
|
2467
|
+
attributeFilter: ["controls"]
|
|
2468
|
+
});
|
|
2469
|
+
return () => {
|
|
2470
|
+
observer.disconnect();
|
|
2471
|
+
};
|
|
2472
|
+
}, []);
|
|
2473
|
+
(0, import_react12.useImperativeHandle)(ref, () => ({
|
|
1116
2474
|
...videoRef.current,
|
|
1117
2475
|
// Custom methods for quality control
|
|
1118
2476
|
getAvailableQualities,
|
|
@@ -1122,27 +2480,30 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1122
2480
|
skipForward,
|
|
1123
2481
|
// Mux methods
|
|
1124
2482
|
updateMuxData,
|
|
2483
|
+
// Live status methods
|
|
2484
|
+
getLiveStatus,
|
|
2485
|
+
seekToLiveEdge,
|
|
1125
2486
|
// Access to underlying instances
|
|
1126
2487
|
getPlayer: () => playerRef.current,
|
|
1127
2488
|
getMuxMonitor: () => null
|
|
1128
|
-
}), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData]);
|
|
2489
|
+
}), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData, getLiveStatus, seekToLiveEdge]);
|
|
1129
2490
|
const isResponsive = !width && !height;
|
|
1130
|
-
const containerClasses = (0, import_tailwind_merge2.twMerge)(containerClassName, "motto-video-container");
|
|
2491
|
+
const containerClasses = (0, import_tailwind_merge2.twMerge)(containerClassName, "motto-video-container relative bg-[#111111] ");
|
|
1131
2492
|
const containerStyle = isResponsive ? {
|
|
1132
2493
|
aspectRatio: aspectRatio.toString()
|
|
1133
2494
|
} : { width, height };
|
|
1134
|
-
const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
|
|
2495
|
+
const videoClasses = isResponsive ? "motto-video-responsive w-full" : "w-full h-full ";
|
|
1135
2496
|
const videoStyle = isResponsive ? {} : { width, height };
|
|
1136
|
-
|
|
2497
|
+
const filteredVideoProps = { ...videoProps };
|
|
2498
|
+
delete filteredVideoProps.controls;
|
|
2499
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1137
2500
|
"div",
|
|
1138
2501
|
{
|
|
1139
2502
|
ref: containerRef,
|
|
1140
2503
|
className: containerClasses,
|
|
1141
2504
|
style: containerStyle,
|
|
1142
|
-
"data-shaka-player-container": true,
|
|
1143
|
-
"data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
|
|
1144
2505
|
children: [
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1146
2507
|
"video",
|
|
1147
2508
|
{
|
|
1148
2509
|
ref: videoRef,
|
|
@@ -1151,17 +2512,11 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1151
2512
|
height: isResponsive ? void 0 : height,
|
|
1152
2513
|
style: videoStyle,
|
|
1153
2514
|
controls: false,
|
|
1154
|
-
|
|
2515
|
+
playsInline: true,
|
|
2516
|
+
...filteredVideoProps
|
|
1155
2517
|
}
|
|
1156
2518
|
),
|
|
1157
|
-
/* @__PURE__ */ (0,
|
|
1158
|
-
imaConfig && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1159
|
-
"div",
|
|
1160
|
-
{
|
|
1161
|
-
ref: adContainerRef,
|
|
1162
|
-
className: "absolute top-0 left-0 w-full h-full pointer-events-auto"
|
|
1163
|
-
}
|
|
1164
|
-
)
|
|
2519
|
+
isInitialLoading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "absolute inset-0 flex items-center justify-center z-20 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Loading, { className: "bg-transparent" }) })
|
|
1165
2520
|
]
|
|
1166
2521
|
}
|
|
1167
2522
|
);
|
|
@@ -1170,16 +2525,16 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1170
2525
|
Player.displayName = "Player";
|
|
1171
2526
|
|
|
1172
2527
|
// src/Video.tsx
|
|
1173
|
-
var
|
|
2528
|
+
var import_react14 = require("react");
|
|
1174
2529
|
var import_tailwind_merge3 = require("tailwind-merge");
|
|
1175
2530
|
var import_react_query = require("@tanstack/react-query");
|
|
1176
2531
|
|
|
1177
2532
|
// src/api/video.ts
|
|
1178
|
-
var fetchVideoData = async (videoId, publicKey, mottoToken) => {
|
|
2533
|
+
var fetchVideoData = async (videoId, publicKey, mottoToken, adsEnabled = false, locale = "en") => {
|
|
1179
2534
|
const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/GetVideo";
|
|
1180
2535
|
const url = new URL(endpoint);
|
|
1181
2536
|
url.searchParams.set("encoding", "json");
|
|
1182
|
-
url.searchParams.set("message", JSON.stringify({ videoId }));
|
|
2537
|
+
url.searchParams.set("message", JSON.stringify({ videoId, enable_ads: adsEnabled, locale }));
|
|
1183
2538
|
const response = await fetch(url, {
|
|
1184
2539
|
method: "GET",
|
|
1185
2540
|
headers: {
|
|
@@ -1193,14 +2548,14 @@ var fetchVideoData = async (videoId, publicKey, mottoToken) => {
|
|
|
1193
2548
|
const data = await response.json();
|
|
1194
2549
|
return data.video;
|
|
1195
2550
|
};
|
|
1196
|
-
async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0) {
|
|
2551
|
+
async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0, adsEnabled = true, locale = "en") {
|
|
1197
2552
|
if (!videoIds || videoIds.length === 0) {
|
|
1198
2553
|
return [];
|
|
1199
2554
|
}
|
|
1200
2555
|
const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/BatchGetVideos";
|
|
1201
2556
|
const url = new URL(endpoint);
|
|
1202
2557
|
url.searchParams.set("encoding", "json");
|
|
1203
|
-
url.searchParams.set("message", JSON.stringify({ videoIds }));
|
|
2558
|
+
url.searchParams.set("message", JSON.stringify({ videoIds, enable_ads: adsEnabled, locale }));
|
|
1204
2559
|
const response = await fetch(url.toString(), {
|
|
1205
2560
|
method: "GET",
|
|
1206
2561
|
headers: {
|
|
@@ -1311,7 +2666,7 @@ var getErrorType = (error, video) => {
|
|
|
1311
2666
|
};
|
|
1312
2667
|
|
|
1313
2668
|
// src/messages/useMessages.tsx
|
|
1314
|
-
var
|
|
2669
|
+
var import_react13 = require("react");
|
|
1315
2670
|
|
|
1316
2671
|
// src/messages/en.json
|
|
1317
2672
|
var en_default = {
|
|
@@ -1613,9 +2968,9 @@ var getBrowserLanguage = () => {
|
|
|
1613
2968
|
return availableLanguages[language] ? language : "en";
|
|
1614
2969
|
};
|
|
1615
2970
|
var useMessages = (locale) => {
|
|
1616
|
-
const [language, setLanguage] = (0,
|
|
1617
|
-
const [translations, setTranslations] = (0,
|
|
1618
|
-
(0,
|
|
2971
|
+
const [language, setLanguage] = (0, import_react13.useState)("en");
|
|
2972
|
+
const [translations, setTranslations] = (0, import_react13.useState)(availableLanguages.en);
|
|
2973
|
+
(0, import_react13.useEffect)(() => {
|
|
1619
2974
|
const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
|
|
1620
2975
|
;
|
|
1621
2976
|
setLanguage(lang);
|
|
@@ -1641,11 +2996,10 @@ var useMessages = (locale) => {
|
|
|
1641
2996
|
var useMessages_default = useMessages;
|
|
1642
2997
|
|
|
1643
2998
|
// src/Video.tsx
|
|
1644
|
-
var
|
|
2999
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1645
3000
|
var Video = ({
|
|
1646
3001
|
videoId,
|
|
1647
3002
|
publicKey,
|
|
1648
|
-
mottoToken,
|
|
1649
3003
|
videoData: providedVideoData,
|
|
1650
3004
|
refetchInterval = 0,
|
|
1651
3005
|
playerName,
|
|
@@ -1653,7 +3007,10 @@ var Video = ({
|
|
|
1653
3007
|
events,
|
|
1654
3008
|
children,
|
|
1655
3009
|
className,
|
|
3010
|
+
auth,
|
|
3011
|
+
settings,
|
|
1656
3012
|
queryOptions = {},
|
|
3013
|
+
adsEnabled = false,
|
|
1657
3014
|
...props
|
|
1658
3015
|
}) => {
|
|
1659
3016
|
const {
|
|
@@ -1662,8 +3019,8 @@ var Video = ({
|
|
|
1662
3019
|
error,
|
|
1663
3020
|
refetch
|
|
1664
3021
|
} = (0, import_react_query.useQuery)({
|
|
1665
|
-
queryKey: ["video", videoId, publicKey, mottoToken],
|
|
1666
|
-
queryFn: () => fetchVideoData(videoId, publicKey, mottoToken),
|
|
3022
|
+
queryKey: ["video", videoId, publicKey, auth?.mottoToken, adsEnabled, locale],
|
|
3023
|
+
queryFn: () => fetchVideoData(videoId, publicKey, auth?.mottoToken, adsEnabled, locale),
|
|
1667
3024
|
enabled: !!videoId && !!publicKey && !providedVideoData,
|
|
1668
3025
|
refetchInterval: refetchInterval > 0 ? refetchInterval : false,
|
|
1669
3026
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -1676,16 +3033,17 @@ var Video = ({
|
|
|
1676
3033
|
const video = providedVideoData || data;
|
|
1677
3034
|
const { t } = useMessages_default(locale);
|
|
1678
3035
|
const activePlaylist = findHLSPlaylist(video);
|
|
1679
|
-
const
|
|
1680
|
-
|
|
3036
|
+
const activePlaylistUrl = activePlaylist?.url ?? activePlaylist?.drm?.widevine?.playlistUrl ?? activePlaylist?.drm?.playready?.playlistUrl ?? activePlaylist?.drm?.fairplay?.playlistUrl;
|
|
3037
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3038
|
+
(0, import_react14.useEffect)(() => {
|
|
1681
3039
|
if (events?.onVideoData && video) {
|
|
1682
3040
|
events.onVideoData(video);
|
|
1683
3041
|
}
|
|
1684
3042
|
}, [video, events]);
|
|
1685
3043
|
if (isLoading || !providedVideoData && !video) {
|
|
1686
|
-
return /* @__PURE__ */ (0,
|
|
3044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "relative w-full h-full bg-[#151515]", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Loading, {}) }) });
|
|
1687
3045
|
}
|
|
1688
|
-
if (!isLoading && video && !
|
|
3046
|
+
if (!isLoading && video && !activePlaylistHasUrl && events?.onEmptyPlaylists) {
|
|
1689
3047
|
events.onEmptyPlaylists();
|
|
1690
3048
|
}
|
|
1691
3049
|
if (error || video?.error) {
|
|
@@ -1696,8 +3054,8 @@ var Video = ({
|
|
|
1696
3054
|
}
|
|
1697
3055
|
const title = t(errorKey) || t("DEFAULT_ERROR");
|
|
1698
3056
|
const description = t(`${errorKey}_DESCRIPTION`) || t("DEFAULT_ERROR_DESCRIPTION");
|
|
1699
|
-
return /* @__PURE__ */ (0,
|
|
1700
|
-
/* @__PURE__ */ (0,
|
|
3057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1701
3059
|
ErrorScreen,
|
|
1702
3060
|
{
|
|
1703
3061
|
title,
|
|
@@ -1707,31 +3065,35 @@ var Video = ({
|
|
|
1707
3065
|
children
|
|
1708
3066
|
] }) });
|
|
1709
3067
|
}
|
|
1710
|
-
if (!
|
|
1711
|
-
return /* @__PURE__ */ (0,
|
|
1712
|
-
/* @__PURE__ */ (0,
|
|
3068
|
+
if (!activePlaylist || !activePlaylistHasUrl) {
|
|
3069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative w-full h-full bg-[#151515]", children: [
|
|
3070
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Title, { title: video?.name || "" }),
|
|
1713
3071
|
children
|
|
1714
3072
|
] }) });
|
|
1715
3073
|
}
|
|
1716
|
-
|
|
1717
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: (0, import_tailwind_merge3.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1718
3075
|
Player,
|
|
1719
3076
|
{
|
|
1720
3077
|
...props,
|
|
1721
|
-
src:
|
|
3078
|
+
src: activePlaylist,
|
|
3079
|
+
managedMode: true,
|
|
1722
3080
|
className: (0, import_tailwind_merge3.twMerge)("video-player-container", className),
|
|
1723
3081
|
events,
|
|
3082
|
+
locale,
|
|
1724
3083
|
containerClassName: "w-full h-full",
|
|
3084
|
+
publicKey,
|
|
3085
|
+
auth,
|
|
3086
|
+
...adsEnabled && video?.ad?.adTagUrl ? { imaConfig: { adTagUrl: video?.ad?.adTagUrl } } : {},
|
|
1725
3087
|
children
|
|
1726
3088
|
}
|
|
1727
3089
|
) }) });
|
|
1728
3090
|
};
|
|
1729
3091
|
|
|
1730
3092
|
// src/Event.tsx
|
|
1731
|
-
var
|
|
3093
|
+
var import_react15 = require("react");
|
|
1732
3094
|
var import_tailwind_merge4 = require("tailwind-merge");
|
|
1733
3095
|
var import_react_query2 = require("@tanstack/react-query");
|
|
1734
|
-
var
|
|
3096
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1735
3097
|
var Event = ({
|
|
1736
3098
|
publicKey,
|
|
1737
3099
|
eventId,
|
|
@@ -1744,6 +3106,7 @@ var Event = ({
|
|
|
1744
3106
|
settings,
|
|
1745
3107
|
auth,
|
|
1746
3108
|
queryOptions = {},
|
|
3109
|
+
adsEnabled = false,
|
|
1747
3110
|
...props
|
|
1748
3111
|
}) => {
|
|
1749
3112
|
const {
|
|
@@ -1761,16 +3124,16 @@ var Event = ({
|
|
|
1761
3124
|
retry: queryOptions.retry ?? 3,
|
|
1762
3125
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
1763
3126
|
});
|
|
1764
|
-
const [activePlaylist, setActivePlaylist] = (0,
|
|
1765
|
-
const [activeVideoId, setActiveVideoId] = (0,
|
|
3127
|
+
const [activePlaylist, setActivePlaylist] = (0, import_react15.useState)();
|
|
3128
|
+
const [activeVideoId, setActiveVideoId] = (0, import_react15.useState)();
|
|
1766
3129
|
const videoIds = eventData?.videoIds ?? [];
|
|
1767
3130
|
const {
|
|
1768
3131
|
data: videosData,
|
|
1769
3132
|
isLoading: videosIsLoading,
|
|
1770
3133
|
error: videosError
|
|
1771
3134
|
} = (0, import_react_query2.useQuery)({
|
|
1772
|
-
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
|
|
1773
|
-
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
|
|
3135
|
+
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
|
|
3136
|
+
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
|
|
1774
3137
|
enabled: !!publicKey && videoIds.length > 0,
|
|
1775
3138
|
refetchInterval: activePlaylist === null ? 3e4 : false,
|
|
1776
3139
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -1778,8 +3141,8 @@ var Event = ({
|
|
|
1778
3141
|
retry: queryOptions.retry ?? 3,
|
|
1779
3142
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
1780
3143
|
});
|
|
1781
|
-
const [loadingApisState, setLoadingApisState] = (0,
|
|
1782
|
-
(0,
|
|
3144
|
+
const [loadingApisState, setLoadingApisState] = (0, import_react15.useState)(true);
|
|
3145
|
+
(0, import_react15.useEffect)(() => {
|
|
1783
3146
|
if (videosData !== void 0) {
|
|
1784
3147
|
setLoadingApisState(false);
|
|
1785
3148
|
const videosWithPlaylists = videosData.filter(
|
|
@@ -1788,9 +3151,11 @@ var Event = ({
|
|
|
1788
3151
|
if (videosWithPlaylists.length > 0) {
|
|
1789
3152
|
let hlsPlaylistFound = false;
|
|
1790
3153
|
for (const video of videosWithPlaylists) {
|
|
1791
|
-
const
|
|
1792
|
-
|
|
1793
|
-
|
|
3154
|
+
const activePlaylist2 = findHLSPlaylist(video);
|
|
3155
|
+
const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
|
|
3156
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3157
|
+
if (activePlaylist2 && activePlaylistHasUrl) {
|
|
3158
|
+
setActivePlaylist(activePlaylist2);
|
|
1794
3159
|
setActiveVideoId(video.id);
|
|
1795
3160
|
hlsPlaylistFound = true;
|
|
1796
3161
|
break;
|
|
@@ -1811,12 +3176,12 @@ var Event = ({
|
|
|
1811
3176
|
}
|
|
1812
3177
|
}, [videosData, eventData]);
|
|
1813
3178
|
const { t } = useMessages_default(locale);
|
|
1814
|
-
(0,
|
|
3179
|
+
(0, import_react15.useEffect)(() => {
|
|
1815
3180
|
if (events?.onEventData && eventData) {
|
|
1816
3181
|
events.onEventData(eventData);
|
|
1817
3182
|
}
|
|
1818
3183
|
}, [eventData, events]);
|
|
1819
|
-
(0,
|
|
3184
|
+
(0, import_react15.useEffect)(() => {
|
|
1820
3185
|
if (events?.onVideoData && activeVideoId && videosData) {
|
|
1821
3186
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
1822
3187
|
if (activeVideo) {
|
|
@@ -1824,12 +3189,17 @@ var Event = ({
|
|
|
1824
3189
|
}
|
|
1825
3190
|
}
|
|
1826
3191
|
}, [activeVideoId, videosData, events]);
|
|
1827
|
-
const [error, setError] = (0,
|
|
1828
|
-
const [loadingPlaylist, setLoadingPlaylist] = (0,
|
|
3192
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
3193
|
+
const [loadingPlaylist, setLoadingPlaylist] = (0, import_react15.useState)(true);
|
|
1829
3194
|
const videosDataError = videosData?.some((video) => !!video.error);
|
|
1830
|
-
(0,
|
|
1831
|
-
if (
|
|
1832
|
-
|
|
3195
|
+
(0, import_react15.useEffect)(() => {
|
|
3196
|
+
if (isEventLoading || videosIsLoading || loadingApisState) {
|
|
3197
|
+
return;
|
|
3198
|
+
}
|
|
3199
|
+
const hasPlayablePlaylist = Boolean(activePlaylist);
|
|
3200
|
+
if (eventError || videosError || videosDataError && !hasPlayablePlaylist) {
|
|
3201
|
+
const firstVideoError = videosData?.find((video) => !!video.error)?.error;
|
|
3202
|
+
const errorObj = eventError || videosError || firstVideoError && new Error(firstVideoError) || new Error("default");
|
|
1833
3203
|
setError(errorObj);
|
|
1834
3204
|
if (events?.onError) {
|
|
1835
3205
|
events.onError(errorObj);
|
|
@@ -1837,8 +3207,18 @@ var Event = ({
|
|
|
1837
3207
|
} else {
|
|
1838
3208
|
setError(null);
|
|
1839
3209
|
}
|
|
1840
|
-
}, [
|
|
1841
|
-
|
|
3210
|
+
}, [
|
|
3211
|
+
eventError,
|
|
3212
|
+
videosError,
|
|
3213
|
+
videosDataError,
|
|
3214
|
+
videosData,
|
|
3215
|
+
events,
|
|
3216
|
+
activePlaylist,
|
|
3217
|
+
isEventLoading,
|
|
3218
|
+
videosIsLoading,
|
|
3219
|
+
loadingApisState
|
|
3220
|
+
]);
|
|
3221
|
+
(0, import_react15.useEffect)(() => {
|
|
1842
3222
|
const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
|
|
1843
3223
|
const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
|
|
1844
3224
|
if (eventLoadedWithNoVideos || allApisLoadedWithPotentialVideos) {
|
|
@@ -1848,7 +3228,7 @@ var Event = ({
|
|
|
1848
3228
|
if (error) {
|
|
1849
3229
|
const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
|
|
1850
3230
|
const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
|
|
1851
|
-
return /* @__PURE__ */ (0,
|
|
3231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: (0, import_tailwind_merge4.twMerge)("md:rounded-2xl overflow-hidden aspect-video", className), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1852
3232
|
ErrorScreen,
|
|
1853
3233
|
{
|
|
1854
3234
|
title,
|
|
@@ -1860,22 +3240,28 @@ var Event = ({
|
|
|
1860
3240
|
events.onEmptyPlaylists();
|
|
1861
3241
|
}
|
|
1862
3242
|
if (loadingPlaylist) {
|
|
1863
|
-
return /* @__PURE__ */ (0,
|
|
3243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: (0, import_tailwind_merge4.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Loading, {}) }) });
|
|
1864
3244
|
}
|
|
1865
3245
|
if (activePlaylist && activeVideoId && videosData) {
|
|
1866
3246
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
1867
|
-
|
|
1868
|
-
|
|
3247
|
+
console.log("activeVideo?.ad?.adTagUrl", activeVideo?.ad?.adTagUrl);
|
|
3248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: (0, import_tailwind_merge4.twMerge)("", className), children: [
|
|
3249
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1869
3250
|
Player,
|
|
1870
3251
|
{
|
|
1871
3252
|
...props,
|
|
1872
3253
|
src: activePlaylist,
|
|
1873
|
-
|
|
3254
|
+
managedMode: true,
|
|
3255
|
+
className: (0, import_tailwind_merge4.twMerge)(className, "peer aspect-video"),
|
|
1874
3256
|
events,
|
|
1875
|
-
|
|
3257
|
+
locale,
|
|
3258
|
+
containerClassName: "w-full h-full",
|
|
3259
|
+
publicKey,
|
|
3260
|
+
auth,
|
|
3261
|
+
...adsEnabled && activeVideo ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
|
|
1876
3262
|
}
|
|
1877
|
-
),
|
|
1878
|
-
!hideTitle && eventData && /* @__PURE__ */ (0,
|
|
3263
|
+
) }),
|
|
3264
|
+
!hideTitle && eventData && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1879
3265
|
TitleAndDescription,
|
|
1880
3266
|
{
|
|
1881
3267
|
title: eventData.title,
|
|
@@ -1884,10 +3270,10 @@ var Event = ({
|
|
|
1884
3270
|
locale
|
|
1885
3271
|
}
|
|
1886
3272
|
)
|
|
1887
|
-
] })
|
|
3273
|
+
] });
|
|
1888
3274
|
}
|
|
1889
3275
|
if (eventData) {
|
|
1890
|
-
return /* @__PURE__ */ (0,
|
|
3276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: (0, import_tailwind_merge4.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1891
3277
|
PreEvent,
|
|
1892
3278
|
{
|
|
1893
3279
|
event: eventData,
|
|
@@ -1909,12 +3295,12 @@ function PreEvent({
|
|
|
1909
3295
|
}) {
|
|
1910
3296
|
const date = new Date(event.startTime);
|
|
1911
3297
|
const now = /* @__PURE__ */ new Date();
|
|
1912
|
-
const [remainingTime, setRemainingTime] = (0,
|
|
3298
|
+
const [remainingTime, setRemainingTime] = (0, import_react15.useState)(
|
|
1913
3299
|
date.getTime() - now.getTime()
|
|
1914
3300
|
);
|
|
1915
3301
|
const shouldBeStarted = remainingTime < 0;
|
|
1916
3302
|
const { t } = useMessages_default(locale);
|
|
1917
|
-
(0,
|
|
3303
|
+
(0, import_react15.useEffect)(() => {
|
|
1918
3304
|
const interval = setInterval(() => {
|
|
1919
3305
|
if (remainingTime < 0) {
|
|
1920
3306
|
clearInterval(interval);
|
|
@@ -1924,29 +3310,28 @@ function PreEvent({
|
|
|
1924
3310
|
}, 1e3);
|
|
1925
3311
|
return () => clearInterval(interval);
|
|
1926
3312
|
}, [date, remainingTime]);
|
|
1927
|
-
const renderCountdown = (0,
|
|
3313
|
+
const renderCountdown = (0, import_react15.useCallback)(() => {
|
|
1928
3314
|
if (shouldBeStarted) {
|
|
1929
|
-
return /* @__PURE__ */ (0,
|
|
3315
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
|
|
1930
3316
|
}
|
|
1931
3317
|
const seconds = Math.floor(remainingTime / 1e3) % 60;
|
|
1932
3318
|
const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
|
|
1933
3319
|
const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
|
|
1934
3320
|
const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
|
|
1935
|
-
return /* @__PURE__ */ (0,
|
|
1936
|
-
/* @__PURE__ */ (0,
|
|
1937
|
-
/* @__PURE__ */ (0,
|
|
3321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "grid grid-flow-col gap-1 md:gap-5 text-center auto-cols-max", children: [
|
|
3322
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3323
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1938
3324
|
"span",
|
|
1939
3325
|
{
|
|
1940
|
-
style: { "--value": days },
|
|
1941
3326
|
"aria-live": "polite",
|
|
1942
3327
|
"aria-label": days.toString(),
|
|
1943
|
-
children: days
|
|
3328
|
+
children: days.toString()
|
|
1944
3329
|
}
|
|
1945
3330
|
) }),
|
|
1946
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
|
|
1947
3332
|
] }),
|
|
1948
|
-
/* @__PURE__ */ (0,
|
|
1949
|
-
/* @__PURE__ */ (0,
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3334
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1950
3335
|
"span",
|
|
1951
3336
|
{
|
|
1952
3337
|
style: { "--value": hours },
|
|
@@ -1955,10 +3340,10 @@ function PreEvent({
|
|
|
1955
3340
|
children: hours?.toString()?.padStart(2, "0")
|
|
1956
3341
|
}
|
|
1957
3342
|
) }),
|
|
1958
|
-
/* @__PURE__ */ (0,
|
|
3343
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
|
|
1959
3344
|
] }),
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
3345
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3346
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1962
3347
|
"span",
|
|
1963
3348
|
{
|
|
1964
3349
|
style: { "--value": minutes },
|
|
@@ -1967,10 +3352,10 @@ function PreEvent({
|
|
|
1967
3352
|
children: minutes?.toString()?.padStart(2, "0")
|
|
1968
3353
|
}
|
|
1969
3354
|
) }),
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
|
|
1971
3356
|
] }),
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
1973
|
-
/* @__PURE__ */ (0,
|
|
3357
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3358
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1974
3359
|
"span",
|
|
1975
3360
|
{
|
|
1976
3361
|
style: { "--value": seconds },
|
|
@@ -1979,12 +3364,12 @@ function PreEvent({
|
|
|
1979
3364
|
children: seconds?.toString()?.padStart(2, "0")
|
|
1980
3365
|
}
|
|
1981
3366
|
) }),
|
|
1982
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
|
|
1983
3368
|
] })
|
|
1984
3369
|
] });
|
|
1985
3370
|
}, [remainingTime, shouldBeStarted, t]);
|
|
1986
|
-
return /* @__PURE__ */ (0,
|
|
1987
|
-
/* @__PURE__ */ (0,
|
|
3371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: event?.posterUrl ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3372
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1988
3373
|
"div",
|
|
1989
3374
|
{
|
|
1990
3375
|
className: "relative overflow-hidden bg-base-200 aspect-video text-base-content w-full h-full flex justify-center items-center flex-col bg-no-repeat bg-cover md:rounded-2xl",
|
|
@@ -1993,10 +3378,10 @@ function PreEvent({
|
|
|
1993
3378
|
backgroundRepeat: "no-repeat",
|
|
1994
3379
|
backgroundSize: "cover"
|
|
1995
3380
|
},
|
|
1996
|
-
children: /* @__PURE__ */ (0,
|
|
3381
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
1997
3382
|
}
|
|
1998
3383
|
),
|
|
1999
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3384
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2000
3385
|
TitleAndDescription,
|
|
2001
3386
|
{
|
|
2002
3387
|
title: event.title,
|
|
@@ -2005,18 +3390,18 @@ function PreEvent({
|
|
|
2005
3390
|
locale
|
|
2006
3391
|
}
|
|
2007
3392
|
)
|
|
2008
|
-
] }) : /* @__PURE__ */ (0,
|
|
2009
|
-
/* @__PURE__ */ (0,
|
|
3393
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3394
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2010
3395
|
"div",
|
|
2011
3396
|
{
|
|
2012
3397
|
className: "relative overflow-hidden md:rounded-2xl bg-base-200 aspect-video text-base-content flex flex-col justify-center items-center w-full h-full bg-cover bg-center bg-no-repeat",
|
|
2013
3398
|
style: {
|
|
2014
3399
|
backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
|
|
2015
3400
|
},
|
|
2016
|
-
children: /* @__PURE__ */ (0,
|
|
3401
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
2017
3402
|
}
|
|
2018
3403
|
),
|
|
2019
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3404
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2020
3405
|
TitleAndDescription,
|
|
2021
3406
|
{
|
|
2022
3407
|
title: event.title,
|
|
@@ -2034,9 +3419,9 @@ var TitleAndDescription = ({
|
|
|
2034
3419
|
locale = "en",
|
|
2035
3420
|
className
|
|
2036
3421
|
}) => {
|
|
2037
|
-
return /* @__PURE__ */ (0,
|
|
2038
|
-
/* @__PURE__ */ (0,
|
|
2039
|
-
startTime ? /* @__PURE__ */ (0,
|
|
3422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: (0, import_tailwind_merge4.twMerge)("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
|
|
3423
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
|
|
3424
|
+
startTime ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-xs md:text-base text-base-content/70 m-event-start-time", children: [
|
|
2040
3425
|
new Date(startTime || "").toLocaleDateString(locale || "default", {
|
|
2041
3426
|
month: "long",
|
|
2042
3427
|
year: "numeric",
|
|
@@ -2049,15 +3434,15 @@ var TitleAndDescription = ({
|
|
|
2049
3434
|
minute: "2-digit"
|
|
2050
3435
|
})
|
|
2051
3436
|
] }) : null,
|
|
2052
|
-
description && /* @__PURE__ */ (0,
|
|
3437
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-xs md:text-xs text-base-content/60 uppercase", children: description })
|
|
2053
3438
|
] });
|
|
2054
3439
|
};
|
|
2055
3440
|
|
|
2056
3441
|
// src/CreativeWork.tsx
|
|
2057
|
-
var
|
|
3442
|
+
var import_react16 = require("react");
|
|
2058
3443
|
var import_tailwind_merge5 = require("tailwind-merge");
|
|
2059
3444
|
var import_react_query3 = require("@tanstack/react-query");
|
|
2060
|
-
var
|
|
3445
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2061
3446
|
var CreativeWork = ({
|
|
2062
3447
|
publicKey,
|
|
2063
3448
|
creativeWorkId,
|
|
@@ -2070,6 +3455,7 @@ var CreativeWork = ({
|
|
|
2070
3455
|
settings,
|
|
2071
3456
|
auth,
|
|
2072
3457
|
queryOptions = {},
|
|
3458
|
+
adsEnabled = false,
|
|
2073
3459
|
...props
|
|
2074
3460
|
}) => {
|
|
2075
3461
|
const {
|
|
@@ -2087,17 +3473,17 @@ var CreativeWork = ({
|
|
|
2087
3473
|
retry: queryOptions.retry ?? 3,
|
|
2088
3474
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
2089
3475
|
});
|
|
2090
|
-
const [activePlaylist, setActivePlaylist] = (0,
|
|
2091
|
-
const [activeVideoId, setActiveVideoId] = (0,
|
|
2092
|
-
const [showCountDown, setShowCountDown] = (0,
|
|
3476
|
+
const [activePlaylist, setActivePlaylist] = (0, import_react16.useState)();
|
|
3477
|
+
const [activeVideoId, setActiveVideoId] = (0, import_react16.useState)();
|
|
3478
|
+
const [showCountDown, setShowCountDown] = (0, import_react16.useState)(false);
|
|
2093
3479
|
const videoIds = creativeWorkData?.videoIds ?? [];
|
|
2094
3480
|
const {
|
|
2095
3481
|
data: videosData,
|
|
2096
3482
|
isLoading: videosIsLoading,
|
|
2097
3483
|
error: videosError
|
|
2098
3484
|
} = (0, import_react_query3.useQuery)({
|
|
2099
|
-
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
|
|
2100
|
-
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
|
|
3485
|
+
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
|
|
3486
|
+
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
|
|
2101
3487
|
enabled: !!publicKey && videoIds.length > 0,
|
|
2102
3488
|
refetchInterval: activePlaylist === null ? 3e4 : false,
|
|
2103
3489
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -2105,8 +3491,8 @@ var CreativeWork = ({
|
|
|
2105
3491
|
retry: queryOptions.retry ?? 3,
|
|
2106
3492
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
2107
3493
|
});
|
|
2108
|
-
const [loadingApisState, setLoadingApisState] = (0,
|
|
2109
|
-
(0,
|
|
3494
|
+
const [loadingApisState, setLoadingApisState] = (0, import_react16.useState)(true);
|
|
3495
|
+
(0, import_react16.useEffect)(() => {
|
|
2110
3496
|
if (videosData !== void 0) {
|
|
2111
3497
|
setLoadingApisState(false);
|
|
2112
3498
|
const videosWithPlaylists = videosData.filter(
|
|
@@ -2115,9 +3501,11 @@ var CreativeWork = ({
|
|
|
2115
3501
|
if (videosWithPlaylists.length > 0) {
|
|
2116
3502
|
let hlsPlaylistFound = false;
|
|
2117
3503
|
for (const video of videosWithPlaylists) {
|
|
2118
|
-
const
|
|
2119
|
-
|
|
2120
|
-
|
|
3504
|
+
const activePlaylist2 = findHLSPlaylist(video);
|
|
3505
|
+
const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
|
|
3506
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3507
|
+
if (activePlaylist2 && activePlaylistHasUrl) {
|
|
3508
|
+
setActivePlaylist(activePlaylist2);
|
|
2121
3509
|
setActiveVideoId(video.id);
|
|
2122
3510
|
hlsPlaylistFound = true;
|
|
2123
3511
|
break;
|
|
@@ -2138,7 +3526,7 @@ var CreativeWork = ({
|
|
|
2138
3526
|
}
|
|
2139
3527
|
}, [videosData, creativeWorkData]);
|
|
2140
3528
|
const { t } = useMessages_default(locale);
|
|
2141
|
-
(0,
|
|
3529
|
+
(0, import_react16.useEffect)(() => {
|
|
2142
3530
|
if (events?.onCreativeWorkData && creativeWorkData) {
|
|
2143
3531
|
events.onCreativeWorkData(creativeWorkData);
|
|
2144
3532
|
}
|
|
@@ -2146,7 +3534,7 @@ var CreativeWork = ({
|
|
|
2146
3534
|
setShowCountDown(true);
|
|
2147
3535
|
}
|
|
2148
3536
|
}, [creativeWorkData, events]);
|
|
2149
|
-
(0,
|
|
3537
|
+
(0, import_react16.useEffect)(() => {
|
|
2150
3538
|
if (events?.onVideoData && activeVideoId && videosData) {
|
|
2151
3539
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
2152
3540
|
if (activeVideo) {
|
|
@@ -2154,9 +3542,9 @@ var CreativeWork = ({
|
|
|
2154
3542
|
}
|
|
2155
3543
|
}
|
|
2156
3544
|
}, [activeVideoId, videosData, events]);
|
|
2157
|
-
const [error, setError] = (0,
|
|
3545
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
2158
3546
|
const videosDataError = videosData?.some((video) => !!video.error);
|
|
2159
|
-
(0,
|
|
3547
|
+
(0, import_react16.useEffect)(() => {
|
|
2160
3548
|
if (creativeWorkError || videosError || videosDataError) {
|
|
2161
3549
|
const errorObj = creativeWorkError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
|
|
2162
3550
|
setError(errorObj);
|
|
@@ -2170,7 +3558,7 @@ var CreativeWork = ({
|
|
|
2170
3558
|
if (error) {
|
|
2171
3559
|
const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
|
|
2172
3560
|
const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
|
|
2173
|
-
return /* @__PURE__ */ (0,
|
|
3561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_tailwind_merge5.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2174
3562
|
ErrorScreen,
|
|
2175
3563
|
{
|
|
2176
3564
|
title,
|
|
@@ -2178,8 +3566,8 @@ var CreativeWork = ({
|
|
|
2178
3566
|
}
|
|
2179
3567
|
) }) });
|
|
2180
3568
|
}
|
|
2181
|
-
const [loadingPlaylist, setLoadingPlaylist] = (0,
|
|
2182
|
-
(0,
|
|
3569
|
+
const [loadingPlaylist, setLoadingPlaylist] = (0, import_react16.useState)(true);
|
|
3570
|
+
(0, import_react16.useEffect)(() => {
|
|
2183
3571
|
const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
|
|
2184
3572
|
const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
|
|
2185
3573
|
const isEventsFinished = !videosIsLoading && videosData && videosData.length > 0 && videosData.every((video) => video.playlists && video.playlists.length === 0);
|
|
@@ -2200,10 +3588,10 @@ var CreativeWork = ({
|
|
|
2200
3588
|
events
|
|
2201
3589
|
]);
|
|
2202
3590
|
if (isCreativeWorkLoading || videosIsLoading || loadingApisState) {
|
|
2203
|
-
return /* @__PURE__ */ (0,
|
|
3591
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_tailwind_merge5.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Loading, {}) }) });
|
|
2204
3592
|
}
|
|
2205
3593
|
if (showCountDown && creativeWorkData) {
|
|
2206
|
-
return /* @__PURE__ */ (0,
|
|
3594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_tailwind_merge5.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full h-full bg-base-200 text-base-content flex justify-center items-center flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2207
3595
|
PreCreativeWork,
|
|
2208
3596
|
{
|
|
2209
3597
|
creativeWork: creativeWorkData,
|
|
@@ -2216,20 +3604,25 @@ var CreativeWork = ({
|
|
|
2216
3604
|
}
|
|
2217
3605
|
if (activeVideoId && activePlaylist && !loadingPlaylist) {
|
|
2218
3606
|
const activeVideo = videosData?.find((video) => video.id === activeVideoId);
|
|
2219
|
-
return /* @__PURE__ */ (0,
|
|
2220
|
-
/* @__PURE__ */ (0,
|
|
3607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_tailwind_merge5.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
3608
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2221
3609
|
Player,
|
|
2222
3610
|
{
|
|
2223
3611
|
...props,
|
|
2224
|
-
className: (0, import_tailwind_merge5.twMerge)(className, "peer"),
|
|
3612
|
+
className: (0, import_tailwind_merge5.twMerge)(className, "peer aspect-video"),
|
|
3613
|
+
managedMode: true,
|
|
2225
3614
|
events: {
|
|
2226
3615
|
...events
|
|
2227
3616
|
},
|
|
2228
3617
|
src: activePlaylist,
|
|
2229
|
-
|
|
3618
|
+
locale,
|
|
3619
|
+
containerClassName: "w-full h-full",
|
|
3620
|
+
publicKey,
|
|
3621
|
+
auth,
|
|
3622
|
+
...adsEnabled && activeVideo?.ad?.adTagUrl ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
|
|
2230
3623
|
}
|
|
2231
3624
|
),
|
|
2232
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3625
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2233
3626
|
TitleAndDescription2,
|
|
2234
3627
|
{
|
|
2235
3628
|
title: creativeWorkData?.title || "",
|
|
@@ -2242,7 +3635,7 @@ var CreativeWork = ({
|
|
|
2242
3635
|
] }) });
|
|
2243
3636
|
}
|
|
2244
3637
|
if (loadingPlaylist) {
|
|
2245
|
-
return /* @__PURE__ */ (0,
|
|
3638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: (0, import_tailwind_merge5.twMerge)("", className), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full aspect-video bg-[#151515]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Loading, {}) }) });
|
|
2246
3639
|
}
|
|
2247
3640
|
return null;
|
|
2248
3641
|
};
|
|
@@ -2255,12 +3648,12 @@ function PreCreativeWork({
|
|
|
2255
3648
|
}) {
|
|
2256
3649
|
const date = new Date(creativeWork.releaseTime);
|
|
2257
3650
|
const now = /* @__PURE__ */ new Date();
|
|
2258
|
-
const [remainingTime, setRemainingTime] = (0,
|
|
3651
|
+
const [remainingTime, setRemainingTime] = (0, import_react16.useState)(
|
|
2259
3652
|
date.getTime() - now.getTime()
|
|
2260
3653
|
);
|
|
2261
3654
|
const shouldBeStarted = remainingTime < 0;
|
|
2262
3655
|
const { t } = useMessages_default(locale);
|
|
2263
|
-
(0,
|
|
3656
|
+
(0, import_react16.useEffect)(() => {
|
|
2264
3657
|
const interval = setInterval(() => {
|
|
2265
3658
|
if (remainingTime < 0) {
|
|
2266
3659
|
clearInterval(interval);
|
|
@@ -2274,27 +3667,26 @@ function PreCreativeWork({
|
|
|
2274
3667
|
}, [date, remainingTime]);
|
|
2275
3668
|
const renderCountdown = () => {
|
|
2276
3669
|
if (shouldBeStarted) {
|
|
2277
|
-
return /* @__PURE__ */ (0,
|
|
3670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
|
|
2278
3671
|
}
|
|
2279
3672
|
const seconds = Math.floor(remainingTime / 1e3) % 60;
|
|
2280
3673
|
const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
|
|
2281
3674
|
const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
|
|
2282
3675
|
const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
|
|
2283
|
-
return /* @__PURE__ */ (0,
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
3676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-flow-col md:gap-5 gap-1 text-center auto-cols-max", children: [
|
|
3677
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3678
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2286
3679
|
"span",
|
|
2287
3680
|
{
|
|
2288
|
-
style: { "--value": days },
|
|
2289
3681
|
"aria-live": "polite",
|
|
2290
3682
|
"aria-label": days.toString(),
|
|
2291
|
-
children: days
|
|
3683
|
+
children: days.toString()
|
|
2292
3684
|
}
|
|
2293
3685
|
) }),
|
|
2294
|
-
/* @__PURE__ */ (0,
|
|
3686
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
|
|
2295
3687
|
] }),
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
3688
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3689
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2298
3690
|
"span",
|
|
2299
3691
|
{
|
|
2300
3692
|
style: { "--value": hours },
|
|
@@ -2303,10 +3695,10 @@ function PreCreativeWork({
|
|
|
2303
3695
|
children: hours?.toString()?.padStart(2, "0")
|
|
2304
3696
|
}
|
|
2305
3697
|
) }),
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
3698
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
|
|
2307
3699
|
] }),
|
|
2308
|
-
/* @__PURE__ */ (0,
|
|
2309
|
-
/* @__PURE__ */ (0,
|
|
3700
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3701
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2310
3702
|
"span",
|
|
2311
3703
|
{
|
|
2312
3704
|
style: { "--value": minutes },
|
|
@@ -2315,10 +3707,10 @@ function PreCreativeWork({
|
|
|
2315
3707
|
children: minutes?.toString()?.padStart(2, "0")
|
|
2316
3708
|
}
|
|
2317
3709
|
) }),
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
3710
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
|
|
2319
3711
|
] }),
|
|
2320
|
-
/* @__PURE__ */ (0,
|
|
2321
|
-
/* @__PURE__ */ (0,
|
|
3712
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3713
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2322
3714
|
"span",
|
|
2323
3715
|
{
|
|
2324
3716
|
style: { "--value": seconds },
|
|
@@ -2327,12 +3719,12 @@ function PreCreativeWork({
|
|
|
2327
3719
|
children: seconds?.toString()?.padStart(2, "0")
|
|
2328
3720
|
}
|
|
2329
3721
|
) }),
|
|
2330
|
-
/* @__PURE__ */ (0,
|
|
3722
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
|
|
2331
3723
|
] })
|
|
2332
3724
|
] });
|
|
2333
3725
|
};
|
|
2334
|
-
return /* @__PURE__ */ (0,
|
|
2335
|
-
/* @__PURE__ */ (0,
|
|
3726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
3727
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2336
3728
|
"div",
|
|
2337
3729
|
{
|
|
2338
3730
|
className: "relative overflow-hidden md:rounded-2xl bg-base-200 aspect-video text-base-content flex flex-col justify-center items-center w-full h-full bg-cover bg-center bg-no-repeat",
|
|
@@ -2340,12 +3732,12 @@ function PreCreativeWork({
|
|
|
2340
3732
|
backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
|
|
2341
3733
|
},
|
|
2342
3734
|
children: [
|
|
2343
|
-
backgroundImageUrl && /* @__PURE__ */ (0,
|
|
2344
|
-
/* @__PURE__ */ (0,
|
|
3735
|
+
backgroundImageUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
|
|
3736
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
2345
3737
|
]
|
|
2346
3738
|
}
|
|
2347
3739
|
),
|
|
2348
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3740
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2349
3741
|
TitleAndDescription2,
|
|
2350
3742
|
{
|
|
2351
3743
|
title: creativeWork.title,
|
|
@@ -2363,9 +3755,9 @@ var TitleAndDescription2 = ({
|
|
|
2363
3755
|
locale = "en",
|
|
2364
3756
|
className
|
|
2365
3757
|
}) => {
|
|
2366
|
-
return /* @__PURE__ */ (0,
|
|
2367
|
-
/* @__PURE__ */ (0,
|
|
2368
|
-
releaseTime ? /* @__PURE__ */ (0,
|
|
3758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: (0, import_tailwind_merge5.twMerge)("mt-3 mb-6 m-event-details-ctn px-4 text-left w-full", className), children: [
|
|
3759
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
|
|
3760
|
+
releaseTime ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
|
|
2369
3761
|
new Date(releaseTime || "").toLocaleDateString(locale || "default", {
|
|
2370
3762
|
month: "long",
|
|
2371
3763
|
year: "numeric",
|
|
@@ -2378,13 +3770,13 @@ var TitleAndDescription2 = ({
|
|
|
2378
3770
|
minute: "2-digit"
|
|
2379
3771
|
})
|
|
2380
3772
|
] }) : null,
|
|
2381
|
-
description && /* @__PURE__ */ (0,
|
|
3773
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
|
|
2382
3774
|
] });
|
|
2383
3775
|
};
|
|
2384
3776
|
|
|
2385
3777
|
// src/QueryProvider.tsx
|
|
2386
3778
|
var import_react_query4 = require("@tanstack/react-query");
|
|
2387
|
-
var
|
|
3779
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2388
3780
|
var queryClient = new import_react_query4.QueryClient({
|
|
2389
3781
|
defaultOptions: {
|
|
2390
3782
|
queries: {
|
|
@@ -2398,14 +3790,17 @@ var queryClient = new import_react_query4.QueryClient({
|
|
|
2398
3790
|
}
|
|
2399
3791
|
});
|
|
2400
3792
|
var QueryProvider = ({ children }) => {
|
|
2401
|
-
return /* @__PURE__ */ (0,
|
|
3793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_query4.QueryClientProvider, { client: queryClient, children });
|
|
2402
3794
|
};
|
|
2403
3795
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2404
3796
|
0 && (module.exports = {
|
|
3797
|
+
BigPlayIcon,
|
|
2405
3798
|
CreativeWork,
|
|
2406
3799
|
Event,
|
|
2407
3800
|
Player,
|
|
2408
3801
|
QueryProvider,
|
|
3802
|
+
SkipBackIcon,
|
|
3803
|
+
SkipForwardIcon,
|
|
2409
3804
|
Video,
|
|
2410
3805
|
queryClient
|
|
2411
3806
|
});
|