@mottosports/motto-video-player 1.0.1-rc.8 → 1.0.1-rc.80
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 +2082 -683
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2029 -631
- 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.80";
|
|
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 {
|
|
750
|
+
}
|
|
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
|
+
});
|
|
98
885
|
}
|
|
99
|
-
|
|
100
|
-
|
|
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) {
|
|
1493
|
+
constructor(onSkipForward, iconSize) {
|
|
375
1494
|
this.onSkipForward = onSkipForward;
|
|
1495
|
+
this.iconSize = iconSize;
|
|
376
1496
|
}
|
|
377
1497
|
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
|
-
});
|
|
1498
|
+
return new SkipForwardButton(rootElement, controls, this.onSkipForward, this.iconSize);
|
|
454
1499
|
}
|
|
455
1500
|
};
|
|
456
|
-
var
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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;
|
|
556
|
-
this.onSkipForward = onSkipForward;
|
|
557
|
-
}
|
|
558
|
-
create(rootElement, controls) {
|
|
559
|
-
return new MobileControlsContainer(rootElement, controls, this.onSkipBack, this.onSkipForward);
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig, seekbarColors, onSkipBack, onSkipForward) => {
|
|
563
|
-
const uiRef = (0, import_react5.useRef)(null);
|
|
564
|
-
const registeredElements = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
|
|
565
|
-
const initializeUI = (0, import_react5.useCallback)(async () => {
|
|
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,9 +1610,9 @@ 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;
|
|
@@ -661,88 +1622,19 @@ var useEventHandlers = (videoRef, handlers) => {
|
|
|
661
1622
|
if (onLoadStart) video.addEventListener("loadstart", onLoadStart);
|
|
662
1623
|
if (onCanPlay) video.addEventListener("canplay", onCanPlay);
|
|
663
1624
|
}, [videoRef, handlers]);
|
|
664
|
-
const cleanupEventListeners = (0,
|
|
1625
|
+
const cleanupEventListeners = (0, import_react7.useCallback)(() => {
|
|
665
1626
|
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);
|
|
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,148 @@ 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 (!player.getManifest || typeof player.getManifest !== "function") {
|
|
1664
|
+
return { isLive: false, isNearEdge: false };
|
|
1665
|
+
}
|
|
1666
|
+
const manifest = player.getManifest();
|
|
1667
|
+
if (!manifest) {
|
|
1668
|
+
return { isLive: false, isNearEdge: false };
|
|
1669
|
+
}
|
|
1670
|
+
const timeline = manifest.presentationTimeline;
|
|
1671
|
+
if (!timeline || typeof timeline.isLive !== "function") {
|
|
1672
|
+
return { isLive: false, isNearEdge: false };
|
|
1673
|
+
}
|
|
1674
|
+
const isLiveStream = timeline.isLive();
|
|
1675
|
+
if (!isLiveStream) return { isLive: false, isNearEdge: false };
|
|
1676
|
+
const videoElement = player.getMediaElement?.();
|
|
1677
|
+
if (!videoElement) return { isLive: true, isNearEdge: false };
|
|
1678
|
+
const liveEdge = timeline.getSeekRangeEnd?.() ?? timeline.getSegmentAvailabilityEnd?.();
|
|
1679
|
+
if (liveEdge === void 0) return { isLive: true, isNearEdge: false };
|
|
1680
|
+
const currentTime = videoElement.currentTime;
|
|
1681
|
+
const timeBehindLive = liveEdge - currentTime;
|
|
1682
|
+
return {
|
|
1683
|
+
isLive: true,
|
|
1684
|
+
isNearEdge: timeBehindLive <= liveThresholdSeconds,
|
|
1685
|
+
liveEdge
|
|
1686
|
+
};
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
console.error("Error checking live status:", error);
|
|
1689
|
+
return { isLive: false, isNearEdge: false };
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
const seekToLiveEdge = () => {
|
|
1693
|
+
const player = playerRef.current;
|
|
1694
|
+
if (!player) return;
|
|
1695
|
+
try {
|
|
1696
|
+
const manifest = player.getManifest();
|
|
1697
|
+
if (!manifest) return;
|
|
1698
|
+
const timeline = manifest.presentationTimeline;
|
|
1699
|
+
const liveEdge = timeline?.getSeekRangeEnd?.() ?? timeline?.getSegmentAvailabilityEnd?.();
|
|
1700
|
+
if (liveEdge !== void 0) {
|
|
1701
|
+
const videoElement = player.getMediaElement?.();
|
|
1702
|
+
if (videoElement) {
|
|
1703
|
+
videoElement.currentTime = liveEdge;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
} catch (error) {
|
|
1707
|
+
console.error("Error seeking to live edge:", error);
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
762
1710
|
(0, import_react9.useEffect)(() => {
|
|
763
1711
|
if (!containerRef.current || !enabled) {
|
|
764
1712
|
return;
|
|
765
1713
|
}
|
|
766
|
-
const
|
|
767
|
-
|
|
1714
|
+
const updateLiveIndicator = (currentTimeElement, status) => {
|
|
1715
|
+
const parent = currentTimeElement.parentElement;
|
|
1716
|
+
if (!parent) return;
|
|
1717
|
+
const existingContainer = parent.querySelector(".live-indicator-container");
|
|
1718
|
+
const isCurrentlyNearEdge = existingContainer?.getAttribute("data-near-edge") === "true";
|
|
1719
|
+
if (existingContainer && status.isNearEdge === isCurrentlyNearEdge) {
|
|
768
1720
|
return;
|
|
769
1721
|
}
|
|
1722
|
+
if (existingContainer) {
|
|
1723
|
+
existingContainer.remove();
|
|
1724
|
+
}
|
|
1725
|
+
const container = document.createElement("span");
|
|
1726
|
+
container.className = "live-indicator-container";
|
|
1727
|
+
container.setAttribute("data-near-edge", status.isNearEdge.toString());
|
|
1728
|
+
container.style.cssText = `
|
|
1729
|
+
display: inline-flex;
|
|
1730
|
+
align-items: center;
|
|
1731
|
+
width: 80px;
|
|
1732
|
+
${!status.isNearEdge ? "cursor: pointer;" : ""}
|
|
1733
|
+
`;
|
|
770
1734
|
const indicator = document.createElement("span");
|
|
771
1735
|
indicator.className = "live-indicator-dot";
|
|
772
1736
|
indicator.style.cssText = `
|
|
773
1737
|
display: inline-block;
|
|
774
1738
|
width: ${indicatorSize}px;
|
|
775
1739
|
height: ${indicatorSize}px;
|
|
776
|
-
background-color: ${indicatorColor};
|
|
1740
|
+
background-color: ${status.isNearEdge ? indicatorColor : "#888888"};
|
|
777
1741
|
border-radius: 50%;
|
|
778
1742
|
margin-right: 6px;
|
|
779
|
-
|
|
780
|
-
${showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
|
|
1743
|
+
${status.isNearEdge && showPulseAnimation ? "animation: pulse-live 2s infinite;" : ""}
|
|
781
1744
|
`;
|
|
782
|
-
|
|
1745
|
+
const liveText = document.createElement("span");
|
|
1746
|
+
liveText.className = "live-indicator-text";
|
|
1747
|
+
liveText.textContent = status.isNearEdge ? "LIVE" : "GO TO LIVE";
|
|
1748
|
+
container.appendChild(indicator);
|
|
1749
|
+
container.appendChild(liveText);
|
|
1750
|
+
if (!status.isNearEdge) {
|
|
1751
|
+
container.addEventListener("click", seekToLiveEdge);
|
|
1752
|
+
}
|
|
1753
|
+
if (status.isNearEdge) {
|
|
1754
|
+
parent.insertBefore(container, currentTimeElement);
|
|
1755
|
+
currentTimeElement.style.display = "none";
|
|
1756
|
+
} else {
|
|
1757
|
+
currentTimeElement.insertAdjacentElement("afterend", container);
|
|
1758
|
+
currentTimeElement.style.display = "";
|
|
1759
|
+
}
|
|
783
1760
|
};
|
|
784
1761
|
const removeLiveIndicator = (currentTimeElement) => {
|
|
785
|
-
const
|
|
786
|
-
if (
|
|
787
|
-
|
|
1762
|
+
const parent = currentTimeElement.parentElement;
|
|
1763
|
+
if (!parent) return;
|
|
1764
|
+
const container = parent.querySelector(".live-indicator-container");
|
|
1765
|
+
if (container) {
|
|
1766
|
+
container.remove();
|
|
1767
|
+
currentTimeElement.style.display = "";
|
|
788
1768
|
}
|
|
789
1769
|
};
|
|
790
1770
|
const checkForLiveContent = () => {
|
|
791
1771
|
const currentTimeElements = containerRef.current?.querySelectorAll(".shaka-current-time");
|
|
1772
|
+
const status = getLiveStatus(playerRef.current);
|
|
1773
|
+
const lastStatus = lastStatusRef.current;
|
|
1774
|
+
if (onLiveStatusChange && (!lastStatus || lastStatus.isLive !== status.isLive || lastStatus.isNearEdge !== status.isNearEdge)) {
|
|
1775
|
+
onLiveStatusChange(status);
|
|
1776
|
+
lastStatusRef.current = { isLive: status.isLive, isNearEdge: status.isNearEdge };
|
|
1777
|
+
}
|
|
792
1778
|
currentTimeElements?.forEach((element) => {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
addLiveIndicator(element);
|
|
1779
|
+
if (status.isLive) {
|
|
1780
|
+
updateLiveIndicator(element, status);
|
|
796
1781
|
} else {
|
|
797
1782
|
removeLiveIndicator(element);
|
|
798
1783
|
}
|
|
799
1784
|
});
|
|
800
1785
|
};
|
|
801
1786
|
checkForLiveContent();
|
|
1787
|
+
intervalRef.current = setInterval(checkForLiveContent, 1e3);
|
|
802
1788
|
observerRef.current = new MutationObserver((mutations) => {
|
|
803
1789
|
let shouldCheck = false;
|
|
804
1790
|
mutations.forEach((mutation) => {
|
|
@@ -824,31 +1810,289 @@ var useLiveIndicator = (containerRef, options = {}) => {
|
|
|
824
1810
|
characterData: true,
|
|
825
1811
|
characterDataOldValue: true
|
|
826
1812
|
});
|
|
827
|
-
const intervalId = setInterval(checkForLiveContent, 1e3);
|
|
828
1813
|
return () => {
|
|
829
1814
|
if (observerRef.current) {
|
|
830
1815
|
observerRef.current.disconnect();
|
|
831
1816
|
}
|
|
832
|
-
|
|
1817
|
+
if (intervalRef.current) {
|
|
1818
|
+
clearInterval(intervalRef.current);
|
|
1819
|
+
}
|
|
833
1820
|
};
|
|
834
|
-
}, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation]);
|
|
1821
|
+
}, [containerRef, enabled, indicatorColor, indicatorSize, showPulseAnimation, liveThresholdSeconds]);
|
|
835
1822
|
return {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1823
|
+
seekToLiveEdge,
|
|
1824
|
+
getLiveStatus: () => getLiveStatus(playerRef.current)
|
|
1825
|
+
};
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
// src/hooks/useKeyboardControls.ts
|
|
1829
|
+
var import_react10 = require("react");
|
|
1830
|
+
var useKeyboardControls = (videoRef, options = {}) => {
|
|
1831
|
+
const { skipBack, skipForward, enabled = true } = options;
|
|
1832
|
+
const isDesktop = (0, import_react10.useCallback)(() => {
|
|
1833
|
+
return window.innerWidth > 767 && !/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
1834
|
+
}, []);
|
|
1835
|
+
const handleKeydown = (0, import_react10.useCallback)((event) => {
|
|
1836
|
+
if (!enabled || !isDesktop() || !videoRef.current) return;
|
|
1837
|
+
const activeElement = document.activeElement;
|
|
1838
|
+
if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable)) {
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
switch (event.key) {
|
|
1842
|
+
case "ArrowLeft":
|
|
1843
|
+
event.preventDefault();
|
|
1844
|
+
skipBack?.();
|
|
1845
|
+
break;
|
|
1846
|
+
case "ArrowRight":
|
|
1847
|
+
event.preventDefault();
|
|
1848
|
+
skipForward?.();
|
|
1849
|
+
break;
|
|
1850
|
+
case " ":
|
|
1851
|
+
case "Space":
|
|
1852
|
+
event.preventDefault();
|
|
1853
|
+
if (videoRef.current.paused) {
|
|
1854
|
+
videoRef.current.play();
|
|
1855
|
+
} else {
|
|
1856
|
+
videoRef.current.pause();
|
|
1857
|
+
}
|
|
1858
|
+
break;
|
|
1859
|
+
}
|
|
1860
|
+
}, [enabled, videoRef, skipBack, skipForward, isDesktop]);
|
|
1861
|
+
(0, import_react10.useEffect)(() => {
|
|
1862
|
+
if (!enabled || !isDesktop()) return;
|
|
1863
|
+
document.addEventListener("keydown", handleKeydown);
|
|
1864
|
+
return () => {
|
|
1865
|
+
document.removeEventListener("keydown", handleKeydown);
|
|
1866
|
+
};
|
|
1867
|
+
}, [handleKeydown, enabled, isDesktop]);
|
|
1868
|
+
return {
|
|
1869
|
+
isDesktop: isDesktop()
|
|
1870
|
+
};
|
|
1871
|
+
};
|
|
1872
|
+
|
|
1873
|
+
// src/hooks/useAdEvents.ts
|
|
1874
|
+
var import_react11 = require("react");
|
|
1875
|
+
var useAdEvents = (playerRef, handlers) => {
|
|
1876
|
+
const listenersRef = (0, import_react11.useRef)([]);
|
|
1877
|
+
const setupAdEventListeners = (0, import_react11.useCallback)(() => {
|
|
1878
|
+
const player = playerRef.current;
|
|
1879
|
+
if (!player) return;
|
|
1880
|
+
const adManager = player.getAdManager();
|
|
1881
|
+
if (!adManager) return;
|
|
1882
|
+
const onAdsManagerLoaded = (event) => {
|
|
1883
|
+
const adsManager = event.getAdsManager();
|
|
1884
|
+
const onAdStarted = () => {
|
|
1885
|
+
console.log("Ad started");
|
|
1886
|
+
handlers.onAdStart?.();
|
|
1887
|
+
};
|
|
1888
|
+
const onAdComplete = () => {
|
|
1889
|
+
console.log("Ad completed");
|
|
1890
|
+
handlers.onAdComplete?.();
|
|
1891
|
+
};
|
|
1892
|
+
const onAdError = (adErrorEvent) => {
|
|
1893
|
+
console.error("Ad error:", adErrorEvent.getError());
|
|
1894
|
+
handlers.onAdError?.(adErrorEvent.getError());
|
|
1895
|
+
};
|
|
1896
|
+
const onAdSkipped = () => {
|
|
1897
|
+
console.log("Ad skipped");
|
|
1898
|
+
handlers.onAdSkipped?.();
|
|
1899
|
+
};
|
|
1900
|
+
const onAdPaused = () => {
|
|
1901
|
+
console.log("Ad paused");
|
|
1902
|
+
handlers.onAdPaused?.();
|
|
1903
|
+
};
|
|
1904
|
+
const onAdResumed = () => {
|
|
1905
|
+
console.log("Ad resumed");
|
|
1906
|
+
handlers.onAdResumed?.();
|
|
1907
|
+
};
|
|
1908
|
+
const onAdProgress = (adProgressData) => {
|
|
1909
|
+
handlers.onAdProgress?.(adProgressData);
|
|
1910
|
+
};
|
|
1911
|
+
const onAllAdsCompleted = () => {
|
|
1912
|
+
console.log("All ads completed");
|
|
1913
|
+
handlers.onAllAdsCompleted?.();
|
|
1914
|
+
};
|
|
1915
|
+
const adEventListeners = [];
|
|
1916
|
+
if (window.google?.ima) {
|
|
1917
|
+
const AdEvent = window.google.ima.AdEvent.Type;
|
|
1918
|
+
const AdErrorEvent = window.google.ima.AdErrorEvent.Type;
|
|
1919
|
+
if (handlers.onAdStart) {
|
|
1920
|
+
adsManager.addEventListener(AdEvent.STARTED, onAdStarted);
|
|
1921
|
+
adEventListeners.push({ event: AdEvent.STARTED, listener: onAdStarted });
|
|
1922
|
+
}
|
|
1923
|
+
if (handlers.onAdComplete) {
|
|
1924
|
+
adsManager.addEventListener(AdEvent.COMPLETE, onAdComplete);
|
|
1925
|
+
adEventListeners.push({ event: AdEvent.COMPLETE, listener: onAdComplete });
|
|
1926
|
+
}
|
|
1927
|
+
if (handlers.onAdError) {
|
|
1928
|
+
adsManager.addEventListener(AdErrorEvent.AD_ERROR, onAdError);
|
|
1929
|
+
adEventListeners.push({ event: AdErrorEvent.AD_ERROR, listener: onAdError });
|
|
1930
|
+
}
|
|
1931
|
+
if (handlers.onAdSkipped) {
|
|
1932
|
+
adsManager.addEventListener(AdEvent.SKIPPED, onAdSkipped);
|
|
1933
|
+
adEventListeners.push({ event: AdEvent.SKIPPED, listener: onAdSkipped });
|
|
1934
|
+
}
|
|
1935
|
+
if (handlers.onAdPaused) {
|
|
1936
|
+
adsManager.addEventListener(AdEvent.PAUSED, onAdPaused);
|
|
1937
|
+
adEventListeners.push({ event: AdEvent.PAUSED, listener: onAdPaused });
|
|
1938
|
+
}
|
|
1939
|
+
if (handlers.onAdResumed) {
|
|
1940
|
+
adsManager.addEventListener(AdEvent.RESUMED, onAdResumed);
|
|
1941
|
+
adEventListeners.push({ event: AdEvent.RESUMED, listener: onAdResumed });
|
|
1942
|
+
}
|
|
1943
|
+
if (handlers.onAdProgress) {
|
|
1944
|
+
adsManager.addEventListener(AdEvent.AD_PROGRESS, onAdProgress);
|
|
1945
|
+
adEventListeners.push({ event: AdEvent.AD_PROGRESS, listener: onAdProgress });
|
|
1946
|
+
}
|
|
1947
|
+
if (handlers.onAllAdsCompleted) {
|
|
1948
|
+
adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, onAllAdsCompleted);
|
|
1949
|
+
adEventListeners.push({ event: AdEvent.ALL_ADS_COMPLETED, listener: onAllAdsCompleted });
|
|
1950
|
+
}
|
|
1951
|
+
listenersRef.current.push({
|
|
1952
|
+
adsManager,
|
|
1953
|
+
listeners: adEventListeners
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
};
|
|
1957
|
+
try {
|
|
1958
|
+
player.addEventListener("ad-started", () => {
|
|
1959
|
+
console.log("Shaka ad-started event");
|
|
1960
|
+
handlers.onAdStart?.();
|
|
1961
|
+
});
|
|
1962
|
+
player.addEventListener("ad-complete", () => {
|
|
1963
|
+
console.log("Shaka ad-complete event");
|
|
1964
|
+
handlers.onAdComplete?.();
|
|
1965
|
+
});
|
|
1966
|
+
player.addEventListener("ad-skipped", () => {
|
|
1967
|
+
console.log("Shaka ad-skipped event");
|
|
1968
|
+
handlers.onAdSkipped?.();
|
|
1969
|
+
});
|
|
1970
|
+
player.addEventListener("ad-error", (event) => {
|
|
1971
|
+
console.error("Shaka ad-error event:", event);
|
|
1972
|
+
handlers.onAdError?.(event);
|
|
1973
|
+
});
|
|
1974
|
+
listenersRef.current.push({
|
|
1975
|
+
type: "shaka",
|
|
1976
|
+
player,
|
|
1977
|
+
events: ["ad-started", "ad-complete", "ad-skipped", "ad-error"]
|
|
1978
|
+
});
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
console.warn("Error setting up ad event listeners:", error);
|
|
1981
|
+
}
|
|
1982
|
+
}, [playerRef, handlers]);
|
|
1983
|
+
const cleanupAdEventListeners = (0, import_react11.useCallback)(() => {
|
|
1984
|
+
try {
|
|
1985
|
+
listenersRef.current.forEach((listenerGroup) => {
|
|
1986
|
+
if (listenerGroup.type === "shaka" && listenerGroup.player) {
|
|
1987
|
+
listenerGroup.events.forEach((eventName) => {
|
|
1988
|
+
try {
|
|
1989
|
+
listenerGroup.player.removeEventListener(eventName, () => {
|
|
1990
|
+
});
|
|
1991
|
+
} catch (e) {
|
|
1992
|
+
console.warn(`Error removing ${eventName} listener:`, e);
|
|
1993
|
+
}
|
|
1994
|
+
});
|
|
1995
|
+
} else if (listenerGroup.adsManager && listenerGroup.listeners) {
|
|
1996
|
+
listenerGroup.listeners.forEach(({ event, listener }) => {
|
|
1997
|
+
try {
|
|
1998
|
+
listenerGroup.adsManager.removeEventListener(event, listener);
|
|
1999
|
+
} catch (e) {
|
|
2000
|
+
console.warn("Error removing ad listener:", e);
|
|
2001
|
+
}
|
|
2002
|
+
});
|
|
842
2003
|
}
|
|
843
2004
|
});
|
|
2005
|
+
listenersRef.current = [];
|
|
2006
|
+
} catch (error) {
|
|
2007
|
+
console.warn("Error cleaning up ad event listeners:", error);
|
|
844
2008
|
}
|
|
2009
|
+
}, []);
|
|
2010
|
+
return {
|
|
2011
|
+
setupAdEventListeners,
|
|
2012
|
+
cleanupAdEventListeners
|
|
845
2013
|
};
|
|
846
2014
|
};
|
|
847
2015
|
|
|
2016
|
+
// src/Player.tsx
|
|
2017
|
+
var import_tailwind_merge2 = require("tailwind-merge");
|
|
2018
|
+
|
|
2019
|
+
// src/utils/scriptLoader.ts
|
|
2020
|
+
var SCRIPT_CONFIGS = {
|
|
2021
|
+
ima: {
|
|
2022
|
+
src: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
|
|
2023
|
+
id: "ima-sdk",
|
|
2024
|
+
type: "text/javascript"
|
|
2025
|
+
},
|
|
2026
|
+
system73: {
|
|
2027
|
+
src: "//cdn.s73cloud.com/4/s73-sdk-shakaplayer.js",
|
|
2028
|
+
id: "system73-sdk",
|
|
2029
|
+
type: "application/javascript"
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
function loadScript(config) {
|
|
2033
|
+
return new Promise((resolve, reject) => {
|
|
2034
|
+
if (document.getElementById(config.id)) {
|
|
2035
|
+
resolve();
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
const script = document.createElement("script");
|
|
2039
|
+
script.id = config.id;
|
|
2040
|
+
script.src = config.src;
|
|
2041
|
+
script.type = config.type || "text/javascript";
|
|
2042
|
+
script.async = true;
|
|
2043
|
+
script.onload = () => resolve();
|
|
2044
|
+
script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
|
|
2045
|
+
document.head.appendChild(script);
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
2048
|
+
function getRequiredScriptLoaders(needsIma, needsSystem73) {
|
|
2049
|
+
const loaders = [];
|
|
2050
|
+
if (needsIma) {
|
|
2051
|
+
loaders.push(loadScript(SCRIPT_CONFIGS.ima));
|
|
2052
|
+
}
|
|
2053
|
+
if (needsSystem73) {
|
|
2054
|
+
loaders.push(loadScript(SCRIPT_CONFIGS.system73));
|
|
2055
|
+
}
|
|
2056
|
+
return loaders;
|
|
2057
|
+
}
|
|
2058
|
+
async function loadScripts(scriptLoaders) {
|
|
2059
|
+
if (scriptLoaders.length === 0) {
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
try {
|
|
2063
|
+
await Promise.all(scriptLoaders);
|
|
2064
|
+
} catch (error) {
|
|
2065
|
+
console.error("Error loading scripts:", error);
|
|
2066
|
+
throw error;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
function waitForGlobal(globalName, timeout = 5e3) {
|
|
2070
|
+
return new Promise((resolve, reject) => {
|
|
2071
|
+
const startTime = Date.now();
|
|
2072
|
+
function checkGlobal() {
|
|
2073
|
+
const global = window[globalName];
|
|
2074
|
+
if (global) {
|
|
2075
|
+
resolve(global);
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
if (Date.now() - startTime > timeout) {
|
|
2079
|
+
reject(new Error(`Timeout waiting for global: ${globalName}`));
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
setTimeout(checkGlobal, 100);
|
|
2083
|
+
}
|
|
2084
|
+
checkGlobal();
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2087
|
+
async function waitForGlobals(globalNames, timeout = 5e3) {
|
|
2088
|
+
const promises = globalNames.map((name) => waitForGlobal(name, timeout));
|
|
2089
|
+
await Promise.all(promises);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
848
2092
|
// src/components/Loading.tsx
|
|
849
2093
|
var import_tailwind_merge = require("tailwind-merge");
|
|
850
|
-
var
|
|
851
|
-
var Loading = ({ className }) => /* @__PURE__ */ (0,
|
|
2094
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2095
|
+
var Loading = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
852
2096
|
"div",
|
|
853
2097
|
{
|
|
854
2098
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -856,17 +2100,36 @@ var Loading = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
|
856
2100
|
className
|
|
857
2101
|
),
|
|
858
2102
|
role: "status",
|
|
859
|
-
children:
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
2103
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: " flex justify-center items-center", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2104
|
+
"svg",
|
|
2105
|
+
{
|
|
2106
|
+
className: "shaka-spinner-svg animate-spin h-12 w-12",
|
|
2107
|
+
viewBox: "0 0 64 64",
|
|
2108
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2109
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2110
|
+
"circle",
|
|
2111
|
+
{
|
|
2112
|
+
className: "shaka-spinner-path",
|
|
2113
|
+
cx: "32",
|
|
2114
|
+
cy: "32",
|
|
2115
|
+
r: "28",
|
|
2116
|
+
strokeWidth: "4",
|
|
2117
|
+
strokeLinecap: "round",
|
|
2118
|
+
stroke: "currentColor",
|
|
2119
|
+
fill: "none",
|
|
2120
|
+
strokeDasharray: "176",
|
|
2121
|
+
strokeDashoffset: "120"
|
|
2122
|
+
}
|
|
2123
|
+
)
|
|
2124
|
+
}
|
|
2125
|
+
) })
|
|
863
2126
|
}
|
|
864
2127
|
);
|
|
865
2128
|
|
|
866
2129
|
// src/components/ErrorScreen.tsx
|
|
867
|
-
var
|
|
868
|
-
var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0,
|
|
869
|
-
/* @__PURE__ */ (0,
|
|
2130
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2131
|
+
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: [
|
|
2132
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
870
2133
|
"svg",
|
|
871
2134
|
{
|
|
872
2135
|
className: "w-24 h-24 m-6",
|
|
@@ -876,7 +2139,7 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0, import_jsx_run
|
|
|
876
2139
|
style: { width: 96 },
|
|
877
2140
|
viewBox: "0 0 24 24",
|
|
878
2141
|
xmlns: "http://www.w3.org/2000/svg",
|
|
879
|
-
children: /* @__PURE__ */ (0,
|
|
2142
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
880
2143
|
"path",
|
|
881
2144
|
{
|
|
882
2145
|
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 +2149,22 @@ var ErrorScreen = ({ title, description }) => /* @__PURE__ */ (0, import_jsx_run
|
|
|
886
2149
|
)
|
|
887
2150
|
}
|
|
888
2151
|
),
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "text-2xl mb-2", children: title || "Playback Error" }),
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-lg", children: description || "Unable to play the video. Please try again later." })
|
|
892
2155
|
] })
|
|
893
2156
|
] }) });
|
|
894
2157
|
|
|
895
2158
|
// 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');
|
|
2159
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2160
|
+
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
2161
|
|
|
943
2162
|
// src/Player.tsx
|
|
944
|
-
var
|
|
945
|
-
var
|
|
946
|
-
var Player = (0, import_react10.forwardRef)(
|
|
2163
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2164
|
+
var Player = (0, import_react12.forwardRef)(
|
|
947
2165
|
({
|
|
948
2166
|
src,
|
|
2167
|
+
managedMode = false,
|
|
949
2168
|
autoPlay = false,
|
|
950
2169
|
loop = false,
|
|
951
2170
|
muted = false,
|
|
@@ -957,25 +2176,48 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
957
2176
|
shakaConfig,
|
|
958
2177
|
drmConfig,
|
|
959
2178
|
muxConfig,
|
|
2179
|
+
system73Config,
|
|
960
2180
|
imaConfig,
|
|
961
2181
|
chromecastConfig,
|
|
962
2182
|
qualityConfig,
|
|
963
2183
|
seekbarConfig,
|
|
2184
|
+
iconSizes,
|
|
964
2185
|
events,
|
|
2186
|
+
locale = "en",
|
|
965
2187
|
containerClassName,
|
|
966
|
-
|
|
2188
|
+
liveThresholdSeconds = 15,
|
|
2189
|
+
publicKey,
|
|
2190
|
+
auth,
|
|
2191
|
+
...videoProps
|
|
967
2192
|
}, ref) => {
|
|
968
|
-
const videoRef = (0,
|
|
969
|
-
const containerRef = (0,
|
|
970
|
-
const
|
|
971
|
-
(0,
|
|
972
|
-
const
|
|
2193
|
+
const videoRef = (0, import_react12.useRef)(null);
|
|
2194
|
+
const containerRef = (0, import_react12.useRef)(null);
|
|
2195
|
+
const [isScriptsLoaded, setIsScriptsLoaded] = (0, import_react12.useState)(false);
|
|
2196
|
+
const [isInitialLoading, setIsInitialLoading] = (0, import_react12.useState)(true);
|
|
2197
|
+
const [bfResetKey, setBfResetKey] = (0, import_react12.useState)(0);
|
|
2198
|
+
const hasPlaylist = !!src && (typeof src === "string" || !!(src.url || src.drm?.widevine?.playlistUrl || src.drm?.playready?.playlistUrl || src.drm?.fairplay?.playlistUrl));
|
|
2199
|
+
(0, import_react12.useImperativeHandle)(ref, () => videoRef.current, []);
|
|
2200
|
+
const { playerRef, initializePlayer, loadManifest, destroyPlayer, isRetrying } = useShakaPlayer({
|
|
973
2201
|
src,
|
|
974
2202
|
shakaConfig,
|
|
975
2203
|
drmConfig,
|
|
976
2204
|
onError: events?.onError,
|
|
977
|
-
onPlayerReady: events?.onPlayerReady
|
|
2205
|
+
onPlayerReady: events?.onPlayerReady,
|
|
2206
|
+
muxConfig,
|
|
2207
|
+
onMuxReady: events?.onMuxReady,
|
|
2208
|
+
onMuxDataUpdate: events?.onMuxDataUpdate,
|
|
2209
|
+
publicKey,
|
|
2210
|
+
mottoToken: auth?.mottoToken,
|
|
2211
|
+
hasAds: !!imaConfig?.adTagUrl,
|
|
2212
|
+
hasSystem73: !!system73Config?.apiKey,
|
|
2213
|
+
apiToken: auth?.apiToken
|
|
978
2214
|
});
|
|
2215
|
+
const {
|
|
2216
|
+
initializeMux,
|
|
2217
|
+
updateMuxData,
|
|
2218
|
+
handleMuxError,
|
|
2219
|
+
destroyMux
|
|
2220
|
+
} = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
|
|
979
2221
|
const {
|
|
980
2222
|
getAvailableQualities,
|
|
981
2223
|
setQuality,
|
|
@@ -988,12 +2230,11 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
988
2230
|
skipDuration,
|
|
989
2231
|
shouldShowSkipControls
|
|
990
2232
|
} = useSkipControls(videoRef, events?.onSkipBack, events?.onSkipForward);
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
} = useMuxAnalytics(playerRef, muxConfig, events?.onMuxReady, events?.onMuxDataUpdate);
|
|
2233
|
+
useKeyboardControls(videoRef, {
|
|
2234
|
+
skipBack,
|
|
2235
|
+
skipForward,
|
|
2236
|
+
enabled: true
|
|
2237
|
+
});
|
|
997
2238
|
const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
|
|
998
2239
|
onPlay: events?.onPlay,
|
|
999
2240
|
onPause: events?.onPause,
|
|
@@ -1009,110 +2250,231 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1009
2250
|
chromecastConfig,
|
|
1010
2251
|
seekbarConfig,
|
|
1011
2252
|
events?.onSkipBack,
|
|
1012
|
-
events?.onSkipForward
|
|
2253
|
+
events?.onSkipForward,
|
|
2254
|
+
iconSizes,
|
|
2255
|
+
locale
|
|
1013
2256
|
);
|
|
1014
|
-
const {
|
|
1015
|
-
enabled: true,
|
|
1016
|
-
onLiveStateChange: (isLive2) => {
|
|
1017
|
-
events?.onLiveStateChange?.(isLive2);
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
useLiveIndicator(containerRef, {
|
|
2257
|
+
const { getLiveStatus, seekToLiveEdge } = useLiveIndicator(containerRef, playerRef, {
|
|
1021
2258
|
enabled: true,
|
|
1022
2259
|
indicatorColor: "#ff0000",
|
|
1023
2260
|
indicatorSize: 8,
|
|
1024
|
-
showPulseAnimation: true
|
|
2261
|
+
showPulseAnimation: true,
|
|
2262
|
+
liveThresholdSeconds,
|
|
2263
|
+
onLiveStatusChange: events?.onLiveStatusChange
|
|
1025
2264
|
});
|
|
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
|
-
}
|
|
2265
|
+
const { setupAdEventListeners, cleanupAdEventListeners } = useAdEvents(playerRef, {
|
|
2266
|
+
onAdStart: events?.onAdStart,
|
|
2267
|
+
onAdComplete: events?.onAdComplete,
|
|
2268
|
+
onAdError: events?.onAdError,
|
|
2269
|
+
onAdSkipped: events?.onAdSkipped,
|
|
2270
|
+
onAdPaused: events?.onAdPaused,
|
|
2271
|
+
onAdResumed: events?.onAdResumed,
|
|
2272
|
+
onAdProgress: events?.onAdProgress,
|
|
2273
|
+
onAllAdsCompleted: events?.onAllAdsCompleted
|
|
2274
|
+
});
|
|
2275
|
+
const initializeSystem73 = (0, import_react12.useCallback)((playerConfig) => {
|
|
2276
|
+
if (!system73Config?.apiKey || !window.S73ShakaPlayerWrapper) {
|
|
2277
|
+
return null;
|
|
1052
2278
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
2279
|
+
console.log("Initializing System73 SDK...");
|
|
2280
|
+
try {
|
|
2281
|
+
const s73Config = {
|
|
2282
|
+
apiKey: system73Config.apiKey,
|
|
2283
|
+
contentSteeringEndpoint: system73Config.contentSteeringEndpoint,
|
|
2284
|
+
channelId: system73Config.channelId
|
|
2285
|
+
};
|
|
2286
|
+
const wrapper = window.S73ShakaPlayerWrapper(s73Config, { shaka: import_shaka_player4.default });
|
|
2287
|
+
wrapper.wrapPlayerConfig(playerConfig);
|
|
2288
|
+
console.log("System73 SDK initialized with config:", s73Config);
|
|
2289
|
+
return wrapper;
|
|
2290
|
+
} catch (error) {
|
|
2291
|
+
console.error("Error initializing System73 SDK:", error);
|
|
2292
|
+
return null;
|
|
2293
|
+
}
|
|
2294
|
+
}, [system73Config]);
|
|
2295
|
+
const initializeAds = (0, import_react12.useCallback)(async () => {
|
|
2296
|
+
if (!imaConfig?.adTagUrl || !playerRef.current || !videoRef.current || !uiRef.current) {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
if (!window.google?.ima) {
|
|
2300
|
+
console.error("Google IMA SDK not available when trying to initialize ads");
|
|
1056
2301
|
return;
|
|
1057
2302
|
}
|
|
1058
2303
|
try {
|
|
1059
|
-
|
|
1060
|
-
|
|
2304
|
+
const player = playerRef.current;
|
|
2305
|
+
const video = videoRef.current;
|
|
2306
|
+
const ui = uiRef.current;
|
|
2307
|
+
const controls2 = ui.getControls();
|
|
2308
|
+
const container = controls2.getClientSideAdContainer();
|
|
2309
|
+
const adManager = player.getAdManager();
|
|
2310
|
+
if (!adManager) {
|
|
2311
|
+
console.error("Ad manager not available");
|
|
2312
|
+
return;
|
|
1061
2313
|
}
|
|
2314
|
+
const google = window.google;
|
|
2315
|
+
let adsRenderingSettings = null;
|
|
2316
|
+
if (imaConfig.adsRenderingSettings) {
|
|
2317
|
+
adsRenderingSettings = imaConfig.adsRenderingSettings;
|
|
2318
|
+
} else if (autoPlay) {
|
|
2319
|
+
adsRenderingSettings = new google.ima.AdsRenderingSettings();
|
|
2320
|
+
adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
|
|
2321
|
+
}
|
|
2322
|
+
adManager.initClientSide(container, video, adsRenderingSettings);
|
|
2323
|
+
const adsRequest = new google.ima.AdsRequest();
|
|
2324
|
+
adsRequest.adTagUrl = imaConfig.adTagUrl;
|
|
2325
|
+
adManager.requestClientSideAds(adsRequest);
|
|
2326
|
+
setupAdEventListeners();
|
|
2327
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
2328
|
+
await loadManifest();
|
|
1062
2329
|
} catch (error) {
|
|
1063
|
-
console.
|
|
2330
|
+
console.error("Error initializing ads:", error);
|
|
1064
2331
|
}
|
|
1065
|
-
};
|
|
1066
|
-
(0,
|
|
2332
|
+
}, [imaConfig, autoPlay, setupAdEventListeners, loadManifest]);
|
|
2333
|
+
(0, import_react12.useEffect)(() => {
|
|
2334
|
+
const loadRequiredScripts = async () => {
|
|
2335
|
+
try {
|
|
2336
|
+
const scriptLoaders = getRequiredScriptLoaders(!!imaConfig?.adTagUrl, !!system73Config?.apiKey);
|
|
2337
|
+
await loadScripts(scriptLoaders);
|
|
2338
|
+
const globalsToWait = [];
|
|
2339
|
+
if (imaConfig?.adTagUrl) {
|
|
2340
|
+
globalsToWait.push("google");
|
|
2341
|
+
}
|
|
2342
|
+
if (system73Config?.apiKey) {
|
|
2343
|
+
globalsToWait.push("S73ShakaPlayerWrapper");
|
|
2344
|
+
}
|
|
2345
|
+
if (globalsToWait.length > 0) {
|
|
2346
|
+
await waitForGlobals(globalsToWait);
|
|
2347
|
+
}
|
|
2348
|
+
setIsScriptsLoaded(true);
|
|
2349
|
+
} catch (error) {
|
|
2350
|
+
console.error("Error loading required scripts:", error);
|
|
2351
|
+
setIsScriptsLoaded(true);
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
loadRequiredScripts();
|
|
2355
|
+
}, [imaConfig?.adTagUrl, system73Config?.apiKey]);
|
|
2356
|
+
(0, import_react12.useEffect)(() => {
|
|
2357
|
+
const onPageShow = (e) => {
|
|
2358
|
+
if (e && e.persisted) {
|
|
2359
|
+
setBfResetKey((k) => k + 1);
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
window.addEventListener("pageshow", onPageShow);
|
|
2363
|
+
return () => window.removeEventListener("pageshow", onPageShow);
|
|
2364
|
+
}, []);
|
|
2365
|
+
(0, import_react12.useEffect)(() => {
|
|
1067
2366
|
const video = videoRef.current;
|
|
1068
|
-
if (!video) return;
|
|
2367
|
+
if (!video || !isScriptsLoaded) return;
|
|
1069
2368
|
const initialize = async () => {
|
|
1070
2369
|
try {
|
|
2370
|
+
console.log("\u{1F680} [Player] Starting initialization...");
|
|
2371
|
+
setIsInitialLoading(true);
|
|
2372
|
+
let system73Wrapper = null;
|
|
2373
|
+
if (system73Config?.apiKey && window.S73ShakaPlayerWrapper) {
|
|
2374
|
+
console.log("\u{1F4E6} [System73] Step 1: Initializing System73 wrapper with config");
|
|
2375
|
+
const playerConfig = { ...shakaConfig };
|
|
2376
|
+
system73Wrapper = initializeSystem73(playerConfig);
|
|
2377
|
+
if (system73Wrapper) {
|
|
2378
|
+
shakaConfig = playerConfig;
|
|
2379
|
+
console.log("\u2705 [System73] Step 1 complete: Wrapper created and config modified");
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
console.log("\u{1F3AC} [Shaka] Step 2: Initializing Shaka Player (auto-load:", !system73Config?.apiKey && !imaConfig?.adTagUrl, ")");
|
|
1071
2383
|
await initializePlayer(video);
|
|
2384
|
+
console.log("\u2705 [Shaka] Step 2 complete: Player initialized");
|
|
2385
|
+
if (system73Wrapper && playerRef.current) {
|
|
2386
|
+
console.log("\u{1F517} [System73] Step 3: Wrapping Shaka player with System73");
|
|
2387
|
+
system73Wrapper.wrapPlayer(playerRef.current);
|
|
2388
|
+
console.log("\u2705 [System73] Step 3 complete: Player wrapped");
|
|
2389
|
+
if (!imaConfig?.adTagUrl) {
|
|
2390
|
+
console.log("\u{1F4FA} [System73] Step 4: Loading manifest");
|
|
2391
|
+
await loadManifest();
|
|
2392
|
+
console.log("\u2705 [System73] Step 4 complete: Manifest loaded");
|
|
2393
|
+
} else {
|
|
2394
|
+
console.log("\u23ED\uFE0F [System73] Skipping manifest load - ads will handle it");
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
console.log("\u{1F4CB} [Player] Setting up event listeners and quality tracking");
|
|
1072
2398
|
setupEventListeners();
|
|
1073
2399
|
const cleanupQuality = setupQualityTracking();
|
|
1074
2400
|
configureQuality();
|
|
2401
|
+
console.log("\u{1F3A8} [UI] Initializing Shaka UI");
|
|
1075
2402
|
await initializeUI();
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
2403
|
+
console.log("\u2705 [UI] UI initialized");
|
|
2404
|
+
if (imaConfig?.adTagUrl && window.google?.ima) {
|
|
2405
|
+
console.log("\u{1F4E2} [Ads] Initializing ads (will load manifest after VAST fetch)");
|
|
2406
|
+
await initializeAds();
|
|
2407
|
+
console.log("\u2705 [Ads] Ads initialized and manifest loaded");
|
|
2408
|
+
}
|
|
2409
|
+
console.log("\u2728 [Player] Initialization complete!");
|
|
1079
2410
|
} catch (error) {
|
|
1080
|
-
console.error("Error during
|
|
2411
|
+
console.error("\u274C [Player] Error during initialization:", error);
|
|
1081
2412
|
handleMuxError(error);
|
|
1082
2413
|
}
|
|
1083
2414
|
};
|
|
1084
2415
|
initialize();
|
|
1085
2416
|
return () => {
|
|
1086
2417
|
cleanupEventListeners();
|
|
2418
|
+
cleanupAdEventListeners();
|
|
1087
2419
|
destroyUI();
|
|
1088
2420
|
destroyMux();
|
|
1089
2421
|
destroyPlayer();
|
|
1090
2422
|
};
|
|
1091
|
-
}, [
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
2423
|
+
}, [managedMode ? hasPlaylist : src, isScriptsLoaded, bfResetKey, managedMode]);
|
|
2424
|
+
(0, import_react12.useEffect)(() => {
|
|
2425
|
+
const video = videoRef.current;
|
|
2426
|
+
if (!video) return;
|
|
2427
|
+
const onLoadStart = () => {
|
|
2428
|
+
setIsInitialLoading(true);
|
|
2429
|
+
};
|
|
2430
|
+
const onCanPlay = () => {
|
|
2431
|
+
setIsInitialLoading(false);
|
|
2432
|
+
};
|
|
2433
|
+
const onPlaying = () => {
|
|
2434
|
+
setIsInitialLoading(false);
|
|
2435
|
+
};
|
|
2436
|
+
video.addEventListener("loadstart", onLoadStart);
|
|
2437
|
+
video.addEventListener("canplay", onCanPlay);
|
|
2438
|
+
video.addEventListener("playing", onPlaying);
|
|
2439
|
+
return () => {
|
|
2440
|
+
video.removeEventListener("loadstart", onLoadStart);
|
|
2441
|
+
video.removeEventListener("canplay", onCanPlay);
|
|
2442
|
+
video.removeEventListener("playing", onPlaying);
|
|
2443
|
+
};
|
|
2444
|
+
}, []);
|
|
2445
|
+
(0, import_react12.useEffect)(() => {
|
|
1107
2446
|
const video = videoRef.current;
|
|
1108
2447
|
if (!video) return;
|
|
1109
2448
|
video.autoplay = autoPlay;
|
|
1110
2449
|
video.loop = loop;
|
|
1111
|
-
video.muted = muted;
|
|
1112
2450
|
video.controls = false;
|
|
1113
2451
|
if (poster) video.poster = poster;
|
|
1114
|
-
}, [autoPlay, loop, muted, poster]);
|
|
1115
|
-
(0,
|
|
2452
|
+
}, [autoPlay, loop, muted, poster, imaConfig?.adTagUrl]);
|
|
2453
|
+
(0, import_react12.useEffect)(() => {
|
|
2454
|
+
const video = videoRef.current;
|
|
2455
|
+
if (!video) return;
|
|
2456
|
+
video.controls = false;
|
|
2457
|
+
video.setAttribute("controls", "false");
|
|
2458
|
+
video.removeAttribute("controls");
|
|
2459
|
+
const observer = new MutationObserver((mutations) => {
|
|
2460
|
+
mutations.forEach((mutation) => {
|
|
2461
|
+
if (mutation.type === "attributes" && mutation.attributeName === "controls") {
|
|
2462
|
+
if (video.hasAttribute("controls")) {
|
|
2463
|
+
video.removeAttribute("controls");
|
|
2464
|
+
video.controls = false;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
});
|
|
2468
|
+
});
|
|
2469
|
+
observer.observe(video, {
|
|
2470
|
+
attributes: true,
|
|
2471
|
+
attributeFilter: ["controls"]
|
|
2472
|
+
});
|
|
2473
|
+
return () => {
|
|
2474
|
+
observer.disconnect();
|
|
2475
|
+
};
|
|
2476
|
+
}, []);
|
|
2477
|
+
(0, import_react12.useImperativeHandle)(ref, () => ({
|
|
1116
2478
|
...videoRef.current,
|
|
1117
2479
|
// Custom methods for quality control
|
|
1118
2480
|
getAvailableQualities,
|
|
@@ -1122,27 +2484,30 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1122
2484
|
skipForward,
|
|
1123
2485
|
// Mux methods
|
|
1124
2486
|
updateMuxData,
|
|
2487
|
+
// Live status methods
|
|
2488
|
+
getLiveStatus,
|
|
2489
|
+
seekToLiveEdge,
|
|
1125
2490
|
// Access to underlying instances
|
|
1126
2491
|
getPlayer: () => playerRef.current,
|
|
1127
2492
|
getMuxMonitor: () => null
|
|
1128
|
-
}), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData]);
|
|
2493
|
+
}), [getAvailableQualities, setQuality, skipBack, skipForward, updateMuxData, getLiveStatus, seekToLiveEdge]);
|
|
1129
2494
|
const isResponsive = !width && !height;
|
|
1130
|
-
const containerClasses = (0, import_tailwind_merge2.twMerge)(containerClassName, "motto-video-container");
|
|
2495
|
+
const containerClasses = (0, import_tailwind_merge2.twMerge)(containerClassName, "motto-video-container relative bg-[#111111] ");
|
|
1131
2496
|
const containerStyle = isResponsive ? {
|
|
1132
2497
|
aspectRatio: aspectRatio.toString()
|
|
1133
2498
|
} : { width, height };
|
|
1134
|
-
const videoClasses = isResponsive ? "motto-video-responsive" : "w-full h-full ";
|
|
2499
|
+
const videoClasses = isResponsive ? "motto-video-responsive w-full" : "w-full h-full ";
|
|
1135
2500
|
const videoStyle = isResponsive ? {} : { width, height };
|
|
1136
|
-
|
|
2501
|
+
const filteredVideoProps = { ...videoProps };
|
|
2502
|
+
delete filteredVideoProps.controls;
|
|
2503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1137
2504
|
"div",
|
|
1138
2505
|
{
|
|
1139
2506
|
ref: containerRef,
|
|
1140
2507
|
className: containerClasses,
|
|
1141
2508
|
style: containerStyle,
|
|
1142
|
-
"data-shaka-player-container": true,
|
|
1143
|
-
"data-shaka-player-cast-receiver-id": chromecastConfig?.receiverApplicationId,
|
|
1144
2509
|
children: [
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1146
2511
|
"video",
|
|
1147
2512
|
{
|
|
1148
2513
|
ref: videoRef,
|
|
@@ -1151,17 +2516,11 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1151
2516
|
height: isResponsive ? void 0 : height,
|
|
1152
2517
|
style: videoStyle,
|
|
1153
2518
|
controls: false,
|
|
1154
|
-
|
|
2519
|
+
playsInline: true,
|
|
2520
|
+
...filteredVideoProps
|
|
1155
2521
|
}
|
|
1156
2522
|
),
|
|
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
|
-
)
|
|
2523
|
+
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
2524
|
]
|
|
1166
2525
|
}
|
|
1167
2526
|
);
|
|
@@ -1170,16 +2529,16 @@ var Player = (0, import_react10.forwardRef)(
|
|
|
1170
2529
|
Player.displayName = "Player";
|
|
1171
2530
|
|
|
1172
2531
|
// src/Video.tsx
|
|
1173
|
-
var
|
|
2532
|
+
var import_react14 = require("react");
|
|
1174
2533
|
var import_tailwind_merge3 = require("tailwind-merge");
|
|
1175
2534
|
var import_react_query = require("@tanstack/react-query");
|
|
1176
2535
|
|
|
1177
2536
|
// src/api/video.ts
|
|
1178
|
-
var fetchVideoData = async (videoId, publicKey, mottoToken) => {
|
|
2537
|
+
var fetchVideoData = async (videoId, publicKey, mottoToken, adsEnabled = false, locale = "en") => {
|
|
1179
2538
|
const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/GetVideo";
|
|
1180
2539
|
const url = new URL(endpoint);
|
|
1181
2540
|
url.searchParams.set("encoding", "json");
|
|
1182
|
-
url.searchParams.set("message", JSON.stringify({ videoId }));
|
|
2541
|
+
url.searchParams.set("message", JSON.stringify({ videoId, enable_ads: adsEnabled, locale }));
|
|
1183
2542
|
const response = await fetch(url, {
|
|
1184
2543
|
method: "GET",
|
|
1185
2544
|
headers: {
|
|
@@ -1193,14 +2552,14 @@ var fetchVideoData = async (videoId, publicKey, mottoToken) => {
|
|
|
1193
2552
|
const data = await response.json();
|
|
1194
2553
|
return data.video;
|
|
1195
2554
|
};
|
|
1196
|
-
async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0) {
|
|
2555
|
+
async function fetchVideosList(publicKey, videoIds, mottoToken, skip = 0, limit = 0, adsEnabled = true, locale = "en") {
|
|
1197
2556
|
if (!videoIds || videoIds.length === 0) {
|
|
1198
2557
|
return [];
|
|
1199
2558
|
}
|
|
1200
2559
|
const endpoint = "https://cda.mottostreaming.com/motto.cda.streaming.video.v1.VideoService/BatchGetVideos";
|
|
1201
2560
|
const url = new URL(endpoint);
|
|
1202
2561
|
url.searchParams.set("encoding", "json");
|
|
1203
|
-
url.searchParams.set("message", JSON.stringify({ videoIds }));
|
|
2562
|
+
url.searchParams.set("message", JSON.stringify({ videoIds, enable_ads: adsEnabled, locale }));
|
|
1204
2563
|
const response = await fetch(url.toString(), {
|
|
1205
2564
|
method: "GET",
|
|
1206
2565
|
headers: {
|
|
@@ -1311,7 +2670,7 @@ var getErrorType = (error, video) => {
|
|
|
1311
2670
|
};
|
|
1312
2671
|
|
|
1313
2672
|
// src/messages/useMessages.tsx
|
|
1314
|
-
var
|
|
2673
|
+
var import_react13 = require("react");
|
|
1315
2674
|
|
|
1316
2675
|
// src/messages/en.json
|
|
1317
2676
|
var en_default = {
|
|
@@ -1613,9 +2972,9 @@ var getBrowserLanguage = () => {
|
|
|
1613
2972
|
return availableLanguages[language] ? language : "en";
|
|
1614
2973
|
};
|
|
1615
2974
|
var useMessages = (locale) => {
|
|
1616
|
-
const [language, setLanguage] = (0,
|
|
1617
|
-
const [translations, setTranslations] = (0,
|
|
1618
|
-
(0,
|
|
2975
|
+
const [language, setLanguage] = (0, import_react13.useState)("en");
|
|
2976
|
+
const [translations, setTranslations] = (0, import_react13.useState)(availableLanguages.en);
|
|
2977
|
+
(0, import_react13.useEffect)(() => {
|
|
1619
2978
|
const lang = !!availableLanguages?.[locale] ? locale : getBrowserLanguage();
|
|
1620
2979
|
;
|
|
1621
2980
|
setLanguage(lang);
|
|
@@ -1641,11 +3000,10 @@ var useMessages = (locale) => {
|
|
|
1641
3000
|
var useMessages_default = useMessages;
|
|
1642
3001
|
|
|
1643
3002
|
// src/Video.tsx
|
|
1644
|
-
var
|
|
3003
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1645
3004
|
var Video = ({
|
|
1646
3005
|
videoId,
|
|
1647
3006
|
publicKey,
|
|
1648
|
-
mottoToken,
|
|
1649
3007
|
videoData: providedVideoData,
|
|
1650
3008
|
refetchInterval = 0,
|
|
1651
3009
|
playerName,
|
|
@@ -1653,7 +3011,10 @@ var Video = ({
|
|
|
1653
3011
|
events,
|
|
1654
3012
|
children,
|
|
1655
3013
|
className,
|
|
3014
|
+
auth,
|
|
3015
|
+
settings,
|
|
1656
3016
|
queryOptions = {},
|
|
3017
|
+
adsEnabled = false,
|
|
1657
3018
|
...props
|
|
1658
3019
|
}) => {
|
|
1659
3020
|
const {
|
|
@@ -1662,8 +3023,8 @@ var Video = ({
|
|
|
1662
3023
|
error,
|
|
1663
3024
|
refetch
|
|
1664
3025
|
} = (0, import_react_query.useQuery)({
|
|
1665
|
-
queryKey: ["video", videoId, publicKey, mottoToken],
|
|
1666
|
-
queryFn: () => fetchVideoData(videoId, publicKey, mottoToken),
|
|
3026
|
+
queryKey: ["video", videoId, publicKey, auth?.mottoToken, adsEnabled, locale],
|
|
3027
|
+
queryFn: () => fetchVideoData(videoId, publicKey, auth?.mottoToken, adsEnabled, locale),
|
|
1667
3028
|
enabled: !!videoId && !!publicKey && !providedVideoData,
|
|
1668
3029
|
refetchInterval: refetchInterval > 0 ? refetchInterval : false,
|
|
1669
3030
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -1676,16 +3037,17 @@ var Video = ({
|
|
|
1676
3037
|
const video = providedVideoData || data;
|
|
1677
3038
|
const { t } = useMessages_default(locale);
|
|
1678
3039
|
const activePlaylist = findHLSPlaylist(video);
|
|
1679
|
-
const
|
|
1680
|
-
|
|
3040
|
+
const activePlaylistUrl = activePlaylist?.url ?? activePlaylist?.drm?.widevine?.playlistUrl ?? activePlaylist?.drm?.playready?.playlistUrl ?? activePlaylist?.drm?.fairplay?.playlistUrl;
|
|
3041
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3042
|
+
(0, import_react14.useEffect)(() => {
|
|
1681
3043
|
if (events?.onVideoData && video) {
|
|
1682
3044
|
events.onVideoData(video);
|
|
1683
3045
|
}
|
|
1684
3046
|
}, [video, events]);
|
|
1685
3047
|
if (isLoading || !providedVideoData && !video) {
|
|
1686
|
-
return /* @__PURE__ */ (0,
|
|
3048
|
+
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
3049
|
}
|
|
1688
|
-
if (!isLoading && video && !
|
|
3050
|
+
if (!isLoading && video && !activePlaylistHasUrl && events?.onEmptyPlaylists) {
|
|
1689
3051
|
events.onEmptyPlaylists();
|
|
1690
3052
|
}
|
|
1691
3053
|
if (error || video?.error) {
|
|
@@ -1696,8 +3058,8 @@ var Video = ({
|
|
|
1696
3058
|
}
|
|
1697
3059
|
const title = t(errorKey) || t("DEFAULT_ERROR");
|
|
1698
3060
|
const description = t(`${errorKey}_DESCRIPTION`) || t("DEFAULT_ERROR_DESCRIPTION");
|
|
1699
|
-
return /* @__PURE__ */ (0,
|
|
1700
|
-
/* @__PURE__ */ (0,
|
|
3061
|
+
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: [
|
|
3062
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1701
3063
|
ErrorScreen,
|
|
1702
3064
|
{
|
|
1703
3065
|
title,
|
|
@@ -1707,31 +3069,35 @@ var Video = ({
|
|
|
1707
3069
|
children
|
|
1708
3070
|
] }) });
|
|
1709
3071
|
}
|
|
1710
|
-
if (!
|
|
1711
|
-
return /* @__PURE__ */ (0,
|
|
1712
|
-
/* @__PURE__ */ (0,
|
|
3072
|
+
if (!activePlaylist || !activePlaylistHasUrl) {
|
|
3073
|
+
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: [
|
|
3074
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Title, { title: video?.name || "" }),
|
|
1713
3075
|
children
|
|
1714
3076
|
] }) });
|
|
1715
3077
|
}
|
|
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)(
|
|
3078
|
+
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
3079
|
Player,
|
|
1719
3080
|
{
|
|
1720
3081
|
...props,
|
|
1721
|
-
src:
|
|
3082
|
+
src: activePlaylist,
|
|
3083
|
+
managedMode: true,
|
|
1722
3084
|
className: (0, import_tailwind_merge3.twMerge)("video-player-container", className),
|
|
1723
3085
|
events,
|
|
3086
|
+
locale,
|
|
1724
3087
|
containerClassName: "w-full h-full",
|
|
3088
|
+
publicKey,
|
|
3089
|
+
auth,
|
|
3090
|
+
...adsEnabled && video?.ad?.adTagUrl ? { imaConfig: { adTagUrl: video?.ad?.adTagUrl } } : {},
|
|
1725
3091
|
children
|
|
1726
3092
|
}
|
|
1727
3093
|
) }) });
|
|
1728
3094
|
};
|
|
1729
3095
|
|
|
1730
3096
|
// src/Event.tsx
|
|
1731
|
-
var
|
|
3097
|
+
var import_react15 = require("react");
|
|
1732
3098
|
var import_tailwind_merge4 = require("tailwind-merge");
|
|
1733
3099
|
var import_react_query2 = require("@tanstack/react-query");
|
|
1734
|
-
var
|
|
3100
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1735
3101
|
var Event = ({
|
|
1736
3102
|
publicKey,
|
|
1737
3103
|
eventId,
|
|
@@ -1744,6 +3110,7 @@ var Event = ({
|
|
|
1744
3110
|
settings,
|
|
1745
3111
|
auth,
|
|
1746
3112
|
queryOptions = {},
|
|
3113
|
+
adsEnabled = false,
|
|
1747
3114
|
...props
|
|
1748
3115
|
}) => {
|
|
1749
3116
|
const {
|
|
@@ -1761,16 +3128,16 @@ var Event = ({
|
|
|
1761
3128
|
retry: queryOptions.retry ?? 3,
|
|
1762
3129
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
1763
3130
|
});
|
|
1764
|
-
const [activePlaylist, setActivePlaylist] = (0,
|
|
1765
|
-
const [activeVideoId, setActiveVideoId] = (0,
|
|
3131
|
+
const [activePlaylist, setActivePlaylist] = (0, import_react15.useState)();
|
|
3132
|
+
const [activeVideoId, setActiveVideoId] = (0, import_react15.useState)();
|
|
1766
3133
|
const videoIds = eventData?.videoIds ?? [];
|
|
1767
3134
|
const {
|
|
1768
3135
|
data: videosData,
|
|
1769
3136
|
isLoading: videosIsLoading,
|
|
1770
3137
|
error: videosError
|
|
1771
3138
|
} = (0, import_react_query2.useQuery)({
|
|
1772
|
-
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
|
|
1773
|
-
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
|
|
3139
|
+
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
|
|
3140
|
+
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
|
|
1774
3141
|
enabled: !!publicKey && videoIds.length > 0,
|
|
1775
3142
|
refetchInterval: activePlaylist === null ? 3e4 : false,
|
|
1776
3143
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -1778,8 +3145,8 @@ var Event = ({
|
|
|
1778
3145
|
retry: queryOptions.retry ?? 3,
|
|
1779
3146
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
1780
3147
|
});
|
|
1781
|
-
const [loadingApisState, setLoadingApisState] = (0,
|
|
1782
|
-
(0,
|
|
3148
|
+
const [loadingApisState, setLoadingApisState] = (0, import_react15.useState)(true);
|
|
3149
|
+
(0, import_react15.useEffect)(() => {
|
|
1783
3150
|
if (videosData !== void 0) {
|
|
1784
3151
|
setLoadingApisState(false);
|
|
1785
3152
|
const videosWithPlaylists = videosData.filter(
|
|
@@ -1788,9 +3155,11 @@ var Event = ({
|
|
|
1788
3155
|
if (videosWithPlaylists.length > 0) {
|
|
1789
3156
|
let hlsPlaylistFound = false;
|
|
1790
3157
|
for (const video of videosWithPlaylists) {
|
|
1791
|
-
const
|
|
1792
|
-
|
|
1793
|
-
|
|
3158
|
+
const activePlaylist2 = findHLSPlaylist(video);
|
|
3159
|
+
const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
|
|
3160
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3161
|
+
if (activePlaylist2 && activePlaylistHasUrl) {
|
|
3162
|
+
setActivePlaylist(activePlaylist2);
|
|
1794
3163
|
setActiveVideoId(video.id);
|
|
1795
3164
|
hlsPlaylistFound = true;
|
|
1796
3165
|
break;
|
|
@@ -1811,12 +3180,12 @@ var Event = ({
|
|
|
1811
3180
|
}
|
|
1812
3181
|
}, [videosData, eventData]);
|
|
1813
3182
|
const { t } = useMessages_default(locale);
|
|
1814
|
-
(0,
|
|
3183
|
+
(0, import_react15.useEffect)(() => {
|
|
1815
3184
|
if (events?.onEventData && eventData) {
|
|
1816
3185
|
events.onEventData(eventData);
|
|
1817
3186
|
}
|
|
1818
3187
|
}, [eventData, events]);
|
|
1819
|
-
(0,
|
|
3188
|
+
(0, import_react15.useEffect)(() => {
|
|
1820
3189
|
if (events?.onVideoData && activeVideoId && videosData) {
|
|
1821
3190
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
1822
3191
|
if (activeVideo) {
|
|
@@ -1824,12 +3193,17 @@ var Event = ({
|
|
|
1824
3193
|
}
|
|
1825
3194
|
}
|
|
1826
3195
|
}, [activeVideoId, videosData, events]);
|
|
1827
|
-
const [error, setError] = (0,
|
|
1828
|
-
const [loadingPlaylist, setLoadingPlaylist] = (0,
|
|
3196
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
3197
|
+
const [loadingPlaylist, setLoadingPlaylist] = (0, import_react15.useState)(true);
|
|
1829
3198
|
const videosDataError = videosData?.some((video) => !!video.error);
|
|
1830
|
-
(0,
|
|
1831
|
-
if (
|
|
1832
|
-
|
|
3199
|
+
(0, import_react15.useEffect)(() => {
|
|
3200
|
+
if (isEventLoading || videosIsLoading || loadingApisState) {
|
|
3201
|
+
return;
|
|
3202
|
+
}
|
|
3203
|
+
const hasPlayablePlaylist = Boolean(activePlaylist);
|
|
3204
|
+
if (eventError || videosError || videosDataError && !hasPlayablePlaylist) {
|
|
3205
|
+
const firstVideoError = videosData?.find((video) => !!video.error)?.error;
|
|
3206
|
+
const errorObj = eventError || videosError || firstVideoError && new Error(firstVideoError) || new Error("default");
|
|
1833
3207
|
setError(errorObj);
|
|
1834
3208
|
if (events?.onError) {
|
|
1835
3209
|
events.onError(errorObj);
|
|
@@ -1837,8 +3211,18 @@ var Event = ({
|
|
|
1837
3211
|
} else {
|
|
1838
3212
|
setError(null);
|
|
1839
3213
|
}
|
|
1840
|
-
}, [
|
|
1841
|
-
|
|
3214
|
+
}, [
|
|
3215
|
+
eventError,
|
|
3216
|
+
videosError,
|
|
3217
|
+
videosDataError,
|
|
3218
|
+
videosData,
|
|
3219
|
+
events,
|
|
3220
|
+
activePlaylist,
|
|
3221
|
+
isEventLoading,
|
|
3222
|
+
videosIsLoading,
|
|
3223
|
+
loadingApisState
|
|
3224
|
+
]);
|
|
3225
|
+
(0, import_react15.useEffect)(() => {
|
|
1842
3226
|
const eventLoadedWithNoVideos = !isEventLoading && eventData && eventData.videoIds && (!eventData.videoIds || eventData?.videoIds?.length === 0) && !loadingApisState;
|
|
1843
3227
|
const allApisLoadedWithPotentialVideos = !isEventLoading && !videosIsLoading && eventData && !loadingApisState;
|
|
1844
3228
|
if (eventLoadedWithNoVideos || allApisLoadedWithPotentialVideos) {
|
|
@@ -1848,7 +3232,7 @@ var Event = ({
|
|
|
1848
3232
|
if (error) {
|
|
1849
3233
|
const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
|
|
1850
3234
|
const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
|
|
1851
|
-
return /* @__PURE__ */ (0,
|
|
3235
|
+
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
3236
|
ErrorScreen,
|
|
1853
3237
|
{
|
|
1854
3238
|
title,
|
|
@@ -1860,22 +3244,28 @@ var Event = ({
|
|
|
1860
3244
|
events.onEmptyPlaylists();
|
|
1861
3245
|
}
|
|
1862
3246
|
if (loadingPlaylist) {
|
|
1863
|
-
return /* @__PURE__ */ (0,
|
|
3247
|
+
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
3248
|
}
|
|
1865
3249
|
if (activePlaylist && activeVideoId && videosData) {
|
|
1866
3250
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
1867
|
-
|
|
1868
|
-
|
|
3251
|
+
console.log("activeVideo?.ad?.adTagUrl", activeVideo?.ad?.adTagUrl);
|
|
3252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: (0, import_tailwind_merge4.twMerge)("", className), children: [
|
|
3253
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1869
3254
|
Player,
|
|
1870
3255
|
{
|
|
1871
3256
|
...props,
|
|
1872
3257
|
src: activePlaylist,
|
|
1873
|
-
|
|
3258
|
+
managedMode: true,
|
|
3259
|
+
className: (0, import_tailwind_merge4.twMerge)(className, "peer aspect-video"),
|
|
1874
3260
|
events,
|
|
1875
|
-
|
|
3261
|
+
locale,
|
|
3262
|
+
containerClassName: "w-full h-full",
|
|
3263
|
+
publicKey,
|
|
3264
|
+
auth,
|
|
3265
|
+
...adsEnabled && activeVideo ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
|
|
1876
3266
|
}
|
|
1877
|
-
),
|
|
1878
|
-
!hideTitle && eventData && /* @__PURE__ */ (0,
|
|
3267
|
+
) }),
|
|
3268
|
+
!hideTitle && eventData && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1879
3269
|
TitleAndDescription,
|
|
1880
3270
|
{
|
|
1881
3271
|
title: eventData.title,
|
|
@@ -1884,10 +3274,10 @@ var Event = ({
|
|
|
1884
3274
|
locale
|
|
1885
3275
|
}
|
|
1886
3276
|
)
|
|
1887
|
-
] })
|
|
3277
|
+
] });
|
|
1888
3278
|
}
|
|
1889
3279
|
if (eventData) {
|
|
1890
|
-
return /* @__PURE__ */ (0,
|
|
3280
|
+
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
3281
|
PreEvent,
|
|
1892
3282
|
{
|
|
1893
3283
|
event: eventData,
|
|
@@ -1909,12 +3299,12 @@ function PreEvent({
|
|
|
1909
3299
|
}) {
|
|
1910
3300
|
const date = new Date(event.startTime);
|
|
1911
3301
|
const now = /* @__PURE__ */ new Date();
|
|
1912
|
-
const [remainingTime, setRemainingTime] = (0,
|
|
3302
|
+
const [remainingTime, setRemainingTime] = (0, import_react15.useState)(
|
|
1913
3303
|
date.getTime() - now.getTime()
|
|
1914
3304
|
);
|
|
1915
3305
|
const shouldBeStarted = remainingTime < 0;
|
|
1916
3306
|
const { t } = useMessages_default(locale);
|
|
1917
|
-
(0,
|
|
3307
|
+
(0, import_react15.useEffect)(() => {
|
|
1918
3308
|
const interval = setInterval(() => {
|
|
1919
3309
|
if (remainingTime < 0) {
|
|
1920
3310
|
clearInterval(interval);
|
|
@@ -1924,29 +3314,28 @@ function PreEvent({
|
|
|
1924
3314
|
}, 1e3);
|
|
1925
3315
|
return () => clearInterval(interval);
|
|
1926
3316
|
}, [date, remainingTime]);
|
|
1927
|
-
const renderCountdown = (0,
|
|
3317
|
+
const renderCountdown = (0, import_react15.useCallback)(() => {
|
|
1928
3318
|
if (shouldBeStarted) {
|
|
1929
|
-
return /* @__PURE__ */ (0,
|
|
3319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
|
|
1930
3320
|
}
|
|
1931
3321
|
const seconds = Math.floor(remainingTime / 1e3) % 60;
|
|
1932
3322
|
const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
|
|
1933
3323
|
const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
|
|
1934
3324
|
const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
|
|
1935
|
-
return /* @__PURE__ */ (0,
|
|
1936
|
-
/* @__PURE__ */ (0,
|
|
1937
|
-
/* @__PURE__ */ (0,
|
|
3325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "grid grid-flow-col gap-1 md:gap-5 text-center auto-cols-max", children: [
|
|
3326
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3327
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1938
3328
|
"span",
|
|
1939
3329
|
{
|
|
1940
|
-
style: { "--value": days },
|
|
1941
3330
|
"aria-live": "polite",
|
|
1942
3331
|
"aria-label": days.toString(),
|
|
1943
|
-
children: days
|
|
3332
|
+
children: days.toString()
|
|
1944
3333
|
}
|
|
1945
3334
|
) }),
|
|
1946
|
-
/* @__PURE__ */ (0,
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
|
|
1947
3336
|
] }),
|
|
1948
|
-
/* @__PURE__ */ (0,
|
|
1949
|
-
/* @__PURE__ */ (0,
|
|
3337
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3338
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1950
3339
|
"span",
|
|
1951
3340
|
{
|
|
1952
3341
|
style: { "--value": hours },
|
|
@@ -1955,10 +3344,10 @@ function PreEvent({
|
|
|
1955
3344
|
children: hours?.toString()?.padStart(2, "0")
|
|
1956
3345
|
}
|
|
1957
3346
|
) }),
|
|
1958
|
-
/* @__PURE__ */ (0,
|
|
3347
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
|
|
1959
3348
|
] }),
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
3349
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3350
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1962
3351
|
"span",
|
|
1963
3352
|
{
|
|
1964
3353
|
style: { "--value": minutes },
|
|
@@ -1967,10 +3356,10 @@ function PreEvent({
|
|
|
1967
3356
|
children: minutes?.toString()?.padStart(2, "0")
|
|
1968
3357
|
}
|
|
1969
3358
|
) }),
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
3359
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
|
|
1971
3360
|
] }),
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
1973
|
-
/* @__PURE__ */ (0,
|
|
3361
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3362
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1974
3363
|
"span",
|
|
1975
3364
|
{
|
|
1976
3365
|
style: { "--value": seconds },
|
|
@@ -1979,12 +3368,12 @@ function PreEvent({
|
|
|
1979
3368
|
children: seconds?.toString()?.padStart(2, "0")
|
|
1980
3369
|
}
|
|
1981
3370
|
) }),
|
|
1982
|
-
/* @__PURE__ */ (0,
|
|
3371
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
|
|
1983
3372
|
] })
|
|
1984
3373
|
] });
|
|
1985
3374
|
}, [remainingTime, shouldBeStarted, t]);
|
|
1986
|
-
return /* @__PURE__ */ (0,
|
|
1987
|
-
/* @__PURE__ */ (0,
|
|
3375
|
+
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: [
|
|
3376
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1988
3377
|
"div",
|
|
1989
3378
|
{
|
|
1990
3379
|
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 +3382,10 @@ function PreEvent({
|
|
|
1993
3382
|
backgroundRepeat: "no-repeat",
|
|
1994
3383
|
backgroundSize: "cover"
|
|
1995
3384
|
},
|
|
1996
|
-
children: /* @__PURE__ */ (0,
|
|
3385
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
1997
3386
|
}
|
|
1998
3387
|
),
|
|
1999
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3388
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2000
3389
|
TitleAndDescription,
|
|
2001
3390
|
{
|
|
2002
3391
|
title: event.title,
|
|
@@ -2005,18 +3394,18 @@ function PreEvent({
|
|
|
2005
3394
|
locale
|
|
2006
3395
|
}
|
|
2007
3396
|
)
|
|
2008
|
-
] }) : /* @__PURE__ */ (0,
|
|
2009
|
-
/* @__PURE__ */ (0,
|
|
3397
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3398
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2010
3399
|
"div",
|
|
2011
3400
|
{
|
|
2012
3401
|
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
3402
|
style: {
|
|
2014
3403
|
backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
|
|
2015
3404
|
},
|
|
2016
|
-
children: /* @__PURE__ */ (0,
|
|
3405
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
2017
3406
|
}
|
|
2018
3407
|
),
|
|
2019
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3408
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2020
3409
|
TitleAndDescription,
|
|
2021
3410
|
{
|
|
2022
3411
|
title: event.title,
|
|
@@ -2034,9 +3423,9 @@ var TitleAndDescription = ({
|
|
|
2034
3423
|
locale = "en",
|
|
2035
3424
|
className
|
|
2036
3425
|
}) => {
|
|
2037
|
-
return /* @__PURE__ */ (0,
|
|
2038
|
-
/* @__PURE__ */ (0,
|
|
2039
|
-
startTime ? /* @__PURE__ */ (0,
|
|
3426
|
+
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: [
|
|
3427
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
|
|
3428
|
+
startTime ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "text-xs md:text-base text-base-content/70 m-event-start-time", children: [
|
|
2040
3429
|
new Date(startTime || "").toLocaleDateString(locale || "default", {
|
|
2041
3430
|
month: "long",
|
|
2042
3431
|
year: "numeric",
|
|
@@ -2049,15 +3438,15 @@ var TitleAndDescription = ({
|
|
|
2049
3438
|
minute: "2-digit"
|
|
2050
3439
|
})
|
|
2051
3440
|
] }) : null,
|
|
2052
|
-
description && /* @__PURE__ */ (0,
|
|
3441
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-xs md:text-xs text-base-content/60 uppercase", children: description })
|
|
2053
3442
|
] });
|
|
2054
3443
|
};
|
|
2055
3444
|
|
|
2056
3445
|
// src/CreativeWork.tsx
|
|
2057
|
-
var
|
|
3446
|
+
var import_react16 = require("react");
|
|
2058
3447
|
var import_tailwind_merge5 = require("tailwind-merge");
|
|
2059
3448
|
var import_react_query3 = require("@tanstack/react-query");
|
|
2060
|
-
var
|
|
3449
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2061
3450
|
var CreativeWork = ({
|
|
2062
3451
|
publicKey,
|
|
2063
3452
|
creativeWorkId,
|
|
@@ -2070,6 +3459,7 @@ var CreativeWork = ({
|
|
|
2070
3459
|
settings,
|
|
2071
3460
|
auth,
|
|
2072
3461
|
queryOptions = {},
|
|
3462
|
+
adsEnabled = false,
|
|
2073
3463
|
...props
|
|
2074
3464
|
}) => {
|
|
2075
3465
|
const {
|
|
@@ -2087,17 +3477,17 @@ var CreativeWork = ({
|
|
|
2087
3477
|
retry: queryOptions.retry ?? 3,
|
|
2088
3478
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
2089
3479
|
});
|
|
2090
|
-
const [activePlaylist, setActivePlaylist] = (0,
|
|
2091
|
-
const [activeVideoId, setActiveVideoId] = (0,
|
|
2092
|
-
const [showCountDown, setShowCountDown] = (0,
|
|
3480
|
+
const [activePlaylist, setActivePlaylist] = (0, import_react16.useState)();
|
|
3481
|
+
const [activeVideoId, setActiveVideoId] = (0, import_react16.useState)();
|
|
3482
|
+
const [showCountDown, setShowCountDown] = (0, import_react16.useState)(false);
|
|
2093
3483
|
const videoIds = creativeWorkData?.videoIds ?? [];
|
|
2094
3484
|
const {
|
|
2095
3485
|
data: videosData,
|
|
2096
3486
|
isLoading: videosIsLoading,
|
|
2097
3487
|
error: videosError
|
|
2098
3488
|
} = (0, import_react_query3.useQuery)({
|
|
2099
|
-
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken],
|
|
2100
|
-
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0),
|
|
3489
|
+
queryKey: ["videos-list", publicKey, videoIds, auth?.mottoToken, adsEnabled, locale],
|
|
3490
|
+
queryFn: () => fetchVideosList(publicKey, videoIds, auth?.mottoToken, 0, 0, adsEnabled, locale),
|
|
2101
3491
|
enabled: !!publicKey && videoIds.length > 0,
|
|
2102
3492
|
refetchInterval: activePlaylist === null ? 3e4 : false,
|
|
2103
3493
|
staleTime: queryOptions.staleTime ?? 5 * 60 * 1e3,
|
|
@@ -2105,8 +3495,8 @@ var CreativeWork = ({
|
|
|
2105
3495
|
retry: queryOptions.retry ?? 3,
|
|
2106
3496
|
retryDelay: queryOptions.retryDelay ?? ((attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4))
|
|
2107
3497
|
});
|
|
2108
|
-
const [loadingApisState, setLoadingApisState] = (0,
|
|
2109
|
-
(0,
|
|
3498
|
+
const [loadingApisState, setLoadingApisState] = (0, import_react16.useState)(true);
|
|
3499
|
+
(0, import_react16.useEffect)(() => {
|
|
2110
3500
|
if (videosData !== void 0) {
|
|
2111
3501
|
setLoadingApisState(false);
|
|
2112
3502
|
const videosWithPlaylists = videosData.filter(
|
|
@@ -2115,9 +3505,11 @@ var CreativeWork = ({
|
|
|
2115
3505
|
if (videosWithPlaylists.length > 0) {
|
|
2116
3506
|
let hlsPlaylistFound = false;
|
|
2117
3507
|
for (const video of videosWithPlaylists) {
|
|
2118
|
-
const
|
|
2119
|
-
|
|
2120
|
-
|
|
3508
|
+
const activePlaylist2 = findHLSPlaylist(video);
|
|
3509
|
+
const activePlaylistUrl = activePlaylist2?.url ?? activePlaylist2?.drm?.widevine?.playlistUrl ?? activePlaylist2?.drm?.playready?.playlistUrl ?? activePlaylist2?.drm?.fairplay?.playlistUrl;
|
|
3510
|
+
const activePlaylistHasUrl = !!activePlaylistUrl;
|
|
3511
|
+
if (activePlaylist2 && activePlaylistHasUrl) {
|
|
3512
|
+
setActivePlaylist(activePlaylist2);
|
|
2121
3513
|
setActiveVideoId(video.id);
|
|
2122
3514
|
hlsPlaylistFound = true;
|
|
2123
3515
|
break;
|
|
@@ -2138,7 +3530,7 @@ var CreativeWork = ({
|
|
|
2138
3530
|
}
|
|
2139
3531
|
}, [videosData, creativeWorkData]);
|
|
2140
3532
|
const { t } = useMessages_default(locale);
|
|
2141
|
-
(0,
|
|
3533
|
+
(0, import_react16.useEffect)(() => {
|
|
2142
3534
|
if (events?.onCreativeWorkData && creativeWorkData) {
|
|
2143
3535
|
events.onCreativeWorkData(creativeWorkData);
|
|
2144
3536
|
}
|
|
@@ -2146,7 +3538,7 @@ var CreativeWork = ({
|
|
|
2146
3538
|
setShowCountDown(true);
|
|
2147
3539
|
}
|
|
2148
3540
|
}, [creativeWorkData, events]);
|
|
2149
|
-
(0,
|
|
3541
|
+
(0, import_react16.useEffect)(() => {
|
|
2150
3542
|
if (events?.onVideoData && activeVideoId && videosData) {
|
|
2151
3543
|
const activeVideo = videosData.find((video) => video.id === activeVideoId);
|
|
2152
3544
|
if (activeVideo) {
|
|
@@ -2154,9 +3546,9 @@ var CreativeWork = ({
|
|
|
2154
3546
|
}
|
|
2155
3547
|
}
|
|
2156
3548
|
}, [activeVideoId, videosData, events]);
|
|
2157
|
-
const [error, setError] = (0,
|
|
3549
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
2158
3550
|
const videosDataError = videosData?.some((video) => !!video.error);
|
|
2159
|
-
(0,
|
|
3551
|
+
(0, import_react16.useEffect)(() => {
|
|
2160
3552
|
if (creativeWorkError || videosError || videosDataError) {
|
|
2161
3553
|
const errorObj = creativeWorkError || videosError || videosData?.find((video) => !!video.error)?.error && new Error(videosData?.find((video) => !!video.error)?.error) || new Error("default");
|
|
2162
3554
|
setError(errorObj);
|
|
@@ -2170,7 +3562,7 @@ var CreativeWork = ({
|
|
|
2170
3562
|
if (error) {
|
|
2171
3563
|
const title = t(error.message)?.length ? t(error.message) : t("DEFAULT_ERROR");
|
|
2172
3564
|
const description = t(`${error.message}_DESCRIPTION`)?.length ? t(`${error.message}_DESCRIPTION`) : t("DEFAULT_ERROR_DESCRIPTION");
|
|
2173
|
-
return /* @__PURE__ */ (0,
|
|
3565
|
+
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
3566
|
ErrorScreen,
|
|
2175
3567
|
{
|
|
2176
3568
|
title,
|
|
@@ -2178,8 +3570,8 @@ var CreativeWork = ({
|
|
|
2178
3570
|
}
|
|
2179
3571
|
) }) });
|
|
2180
3572
|
}
|
|
2181
|
-
const [loadingPlaylist, setLoadingPlaylist] = (0,
|
|
2182
|
-
(0,
|
|
3573
|
+
const [loadingPlaylist, setLoadingPlaylist] = (0, import_react16.useState)(true);
|
|
3574
|
+
(0, import_react16.useEffect)(() => {
|
|
2183
3575
|
const creativeWorkLoadedWithNoVideos = !isCreativeWorkLoading && creativeWorkData && creativeWorkData.videoIds && creativeWorkData.videoIds.length === 0;
|
|
2184
3576
|
const creativeWorkLoadedWithNoData = !isCreativeWorkLoading && creativeWorkData && !creativeWorkData.videoIds;
|
|
2185
3577
|
const isEventsFinished = !videosIsLoading && videosData && videosData.length > 0 && videosData.every((video) => video.playlists && video.playlists.length === 0);
|
|
@@ -2200,10 +3592,10 @@ var CreativeWork = ({
|
|
|
2200
3592
|
events
|
|
2201
3593
|
]);
|
|
2202
3594
|
if (isCreativeWorkLoading || videosIsLoading || loadingApisState) {
|
|
2203
|
-
return /* @__PURE__ */ (0,
|
|
3595
|
+
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
3596
|
}
|
|
2205
3597
|
if (showCountDown && creativeWorkData) {
|
|
2206
|
-
return /* @__PURE__ */ (0,
|
|
3598
|
+
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
3599
|
PreCreativeWork,
|
|
2208
3600
|
{
|
|
2209
3601
|
creativeWork: creativeWorkData,
|
|
@@ -2216,20 +3608,25 @@ var CreativeWork = ({
|
|
|
2216
3608
|
}
|
|
2217
3609
|
if (activeVideoId && activePlaylist && !loadingPlaylist) {
|
|
2218
3610
|
const activeVideo = videosData?.find((video) => video.id === activeVideoId);
|
|
2219
|
-
return /* @__PURE__ */ (0,
|
|
2220
|
-
/* @__PURE__ */ (0,
|
|
3611
|
+
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: [
|
|
3612
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2221
3613
|
Player,
|
|
2222
3614
|
{
|
|
2223
3615
|
...props,
|
|
2224
|
-
className: (0, import_tailwind_merge5.twMerge)(className, "peer"),
|
|
3616
|
+
className: (0, import_tailwind_merge5.twMerge)(className, "peer aspect-video"),
|
|
3617
|
+
managedMode: true,
|
|
2225
3618
|
events: {
|
|
2226
3619
|
...events
|
|
2227
3620
|
},
|
|
2228
3621
|
src: activePlaylist,
|
|
2229
|
-
|
|
3622
|
+
locale,
|
|
3623
|
+
containerClassName: "w-full h-full",
|
|
3624
|
+
publicKey,
|
|
3625
|
+
auth,
|
|
3626
|
+
...adsEnabled && activeVideo?.ad?.adTagUrl ? { imaConfig: { adTagUrl: activeVideo?.ad?.adTagUrl } } : {}
|
|
2230
3627
|
}
|
|
2231
3628
|
),
|
|
2232
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3629
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2233
3630
|
TitleAndDescription2,
|
|
2234
3631
|
{
|
|
2235
3632
|
title: creativeWorkData?.title || "",
|
|
@@ -2242,7 +3639,7 @@ var CreativeWork = ({
|
|
|
2242
3639
|
] }) });
|
|
2243
3640
|
}
|
|
2244
3641
|
if (loadingPlaylist) {
|
|
2245
|
-
return /* @__PURE__ */ (0,
|
|
3642
|
+
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
3643
|
}
|
|
2247
3644
|
return null;
|
|
2248
3645
|
};
|
|
@@ -2255,12 +3652,12 @@ function PreCreativeWork({
|
|
|
2255
3652
|
}) {
|
|
2256
3653
|
const date = new Date(creativeWork.releaseTime);
|
|
2257
3654
|
const now = /* @__PURE__ */ new Date();
|
|
2258
|
-
const [remainingTime, setRemainingTime] = (0,
|
|
3655
|
+
const [remainingTime, setRemainingTime] = (0, import_react16.useState)(
|
|
2259
3656
|
date.getTime() - now.getTime()
|
|
2260
3657
|
);
|
|
2261
3658
|
const shouldBeStarted = remainingTime < 0;
|
|
2262
3659
|
const { t } = useMessages_default(locale);
|
|
2263
|
-
(0,
|
|
3660
|
+
(0, import_react16.useEffect)(() => {
|
|
2264
3661
|
const interval = setInterval(() => {
|
|
2265
3662
|
if (remainingTime < 0) {
|
|
2266
3663
|
clearInterval(interval);
|
|
@@ -2274,27 +3671,26 @@ function PreCreativeWork({
|
|
|
2274
3671
|
}, [date, remainingTime]);
|
|
2275
3672
|
const renderCountdown = () => {
|
|
2276
3673
|
if (shouldBeStarted) {
|
|
2277
|
-
return /* @__PURE__ */ (0,
|
|
3674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-base-content text-xl", children: t("EVENT_NOT_STARTED") });
|
|
2278
3675
|
}
|
|
2279
3676
|
const seconds = Math.floor(remainingTime / 1e3) % 60;
|
|
2280
3677
|
const minutes = Math.floor(remainingTime / 1e3 / 60) % 60;
|
|
2281
3678
|
const hours = Math.floor(remainingTime / 1e3 / 60 / 60) % 24;
|
|
2282
3679
|
const days = Math.floor(remainingTime / 1e3 / 60 / 60 / 24);
|
|
2283
|
-
return /* @__PURE__ */ (0,
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
3680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-flow-col md:gap-5 gap-1 text-center auto-cols-max", children: [
|
|
3681
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3682
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2286
3683
|
"span",
|
|
2287
3684
|
{
|
|
2288
|
-
style: { "--value": days },
|
|
2289
3685
|
"aria-live": "polite",
|
|
2290
3686
|
"aria-label": days.toString(),
|
|
2291
|
-
children: days
|
|
3687
|
+
children: days.toString()
|
|
2292
3688
|
}
|
|
2293
3689
|
) }),
|
|
2294
|
-
/* @__PURE__ */ (0,
|
|
3690
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("DAYS") })
|
|
2295
3691
|
] }),
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
3692
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3693
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2298
3694
|
"span",
|
|
2299
3695
|
{
|
|
2300
3696
|
style: { "--value": hours },
|
|
@@ -2303,10 +3699,10 @@ function PreCreativeWork({
|
|
|
2303
3699
|
children: hours?.toString()?.padStart(2, "0")
|
|
2304
3700
|
}
|
|
2305
3701
|
) }),
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
3702
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("HOURS") })
|
|
2307
3703
|
] }),
|
|
2308
|
-
/* @__PURE__ */ (0,
|
|
2309
|
-
/* @__PURE__ */ (0,
|
|
3704
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3705
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2310
3706
|
"span",
|
|
2311
3707
|
{
|
|
2312
3708
|
style: { "--value": minutes },
|
|
@@ -2315,10 +3711,10 @@ function PreCreativeWork({
|
|
|
2315
3711
|
children: minutes?.toString()?.padStart(2, "0")
|
|
2316
3712
|
}
|
|
2317
3713
|
) }),
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
3714
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("MINUTES") })
|
|
2319
3715
|
] }),
|
|
2320
|
-
/* @__PURE__ */ (0,
|
|
2321
|
-
/* @__PURE__ */ (0,
|
|
3716
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col p-2 bg-neutral rounded-box text-neutral-content", children: [
|
|
3717
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "countdown font-mono text-lg md:text-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2322
3718
|
"span",
|
|
2323
3719
|
{
|
|
2324
3720
|
style: { "--value": seconds },
|
|
@@ -2327,12 +3723,12 @@ function PreCreativeWork({
|
|
|
2327
3723
|
children: seconds?.toString()?.padStart(2, "0")
|
|
2328
3724
|
}
|
|
2329
3725
|
) }),
|
|
2330
|
-
/* @__PURE__ */ (0,
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs uppercase tracking-widest mt-1", children: t("SECONDS") })
|
|
2331
3727
|
] })
|
|
2332
3728
|
] });
|
|
2333
3729
|
};
|
|
2334
|
-
return /* @__PURE__ */ (0,
|
|
2335
|
-
/* @__PURE__ */ (0,
|
|
3730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
3731
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2336
3732
|
"div",
|
|
2337
3733
|
{
|
|
2338
3734
|
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 +3736,12 @@ function PreCreativeWork({
|
|
|
2340
3736
|
backgroundImage: backgroundImageUrl ? `url(${backgroundImageUrl})` : ""
|
|
2341
3737
|
},
|
|
2342
3738
|
children: [
|
|
2343
|
-
backgroundImageUrl && /* @__PURE__ */ (0,
|
|
2344
|
-
/* @__PURE__ */ (0,
|
|
3739
|
+
backgroundImageUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "absolute inset-0 bg-black bg-opacity-40" }),
|
|
3740
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative z-10", children: renderCountdown() })
|
|
2345
3741
|
]
|
|
2346
3742
|
}
|
|
2347
3743
|
),
|
|
2348
|
-
!hideTitle && /* @__PURE__ */ (0,
|
|
3744
|
+
!hideTitle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2349
3745
|
TitleAndDescription2,
|
|
2350
3746
|
{
|
|
2351
3747
|
title: creativeWork.title,
|
|
@@ -2363,9 +3759,9 @@ var TitleAndDescription2 = ({
|
|
|
2363
3759
|
locale = "en",
|
|
2364
3760
|
className
|
|
2365
3761
|
}) => {
|
|
2366
|
-
return /* @__PURE__ */ (0,
|
|
2367
|
-
/* @__PURE__ */ (0,
|
|
2368
|
-
releaseTime ? /* @__PURE__ */ (0,
|
|
3762
|
+
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: [
|
|
3763
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-base md:text-xl m-event-title text-base-content font-medium", children: title }),
|
|
3764
|
+
releaseTime ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "text-sm md:text-base text-base-content/70 m-event-start-time", children: [
|
|
2369
3765
|
new Date(releaseTime || "").toLocaleDateString(locale || "default", {
|
|
2370
3766
|
month: "long",
|
|
2371
3767
|
year: "numeric",
|
|
@@ -2378,13 +3774,13 @@ var TitleAndDescription2 = ({
|
|
|
2378
3774
|
minute: "2-digit"
|
|
2379
3775
|
})
|
|
2380
3776
|
] }) : null,
|
|
2381
|
-
description && /* @__PURE__ */ (0,
|
|
3777
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-xs md:text-sm text-base-content/60 uppercase", children: description })
|
|
2382
3778
|
] });
|
|
2383
3779
|
};
|
|
2384
3780
|
|
|
2385
3781
|
// src/QueryProvider.tsx
|
|
2386
3782
|
var import_react_query4 = require("@tanstack/react-query");
|
|
2387
|
-
var
|
|
3783
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2388
3784
|
var queryClient = new import_react_query4.QueryClient({
|
|
2389
3785
|
defaultOptions: {
|
|
2390
3786
|
queries: {
|
|
@@ -2398,14 +3794,17 @@ var queryClient = new import_react_query4.QueryClient({
|
|
|
2398
3794
|
}
|
|
2399
3795
|
});
|
|
2400
3796
|
var QueryProvider = ({ children }) => {
|
|
2401
|
-
return /* @__PURE__ */ (0,
|
|
3797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_query4.QueryClientProvider, { client: queryClient, children });
|
|
2402
3798
|
};
|
|
2403
3799
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2404
3800
|
0 && (module.exports = {
|
|
3801
|
+
BigPlayIcon,
|
|
2405
3802
|
CreativeWork,
|
|
2406
3803
|
Event,
|
|
2407
3804
|
Player,
|
|
2408
3805
|
QueryProvider,
|
|
3806
|
+
SkipBackIcon,
|
|
3807
|
+
SkipForwardIcon,
|
|
2409
3808
|
Video,
|
|
2410
3809
|
queryClient
|
|
2411
3810
|
});
|