unified-video-framework 1.4.151 → 1.4.153
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/package.json +1 -1
- package/packages/core/dist/chapter-manager.d.ts +39 -0
- package/packages/core/dist/chapter-manager.d.ts.map +1 -0
- package/packages/core/dist/chapter-manager.js +173 -0
- package/packages/core/dist/chapter-manager.js.map +1 -0
- package/packages/core/dist/index.d.ts +2 -0
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +1 -0
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts +10 -0
- package/packages/core/dist/interfaces/IVideoPlayer.d.ts.map +1 -1
- package/packages/core/dist/interfaces.d.ts +33 -1
- package/packages/core/dist/interfaces.d.ts.map +1 -1
- package/packages/core/package.json +2 -2
- package/packages/core/src/chapter-manager.ts +290 -0
- package/packages/core/src/index.ts +4 -0
- package/packages/core/src/interfaces/IVideoPlayer.ts +11 -0
- package/packages/core/src/interfaces.ts +47 -1
- package/packages/web/dist/WebPlayer.d.ts +24 -1
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +472 -1
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/chapters/ChapterManager.d.ts +38 -0
- package/packages/web/dist/chapters/ChapterManager.d.ts.map +1 -0
- package/packages/web/dist/chapters/ChapterManager.js +291 -0
- package/packages/web/dist/chapters/ChapterManager.js.map +1 -0
- package/packages/web/dist/chapters/SkipButtonController.d.ts +31 -0
- package/packages/web/dist/chapters/SkipButtonController.d.ts.map +1 -0
- package/packages/web/dist/chapters/SkipButtonController.js +213 -0
- package/packages/web/dist/chapters/SkipButtonController.js.map +1 -0
- package/packages/web/dist/chapters/UserPreferencesManager.d.ts +25 -0
- package/packages/web/dist/chapters/UserPreferencesManager.d.ts.map +1 -0
- package/packages/web/dist/chapters/UserPreferencesManager.js +232 -0
- package/packages/web/dist/chapters/UserPreferencesManager.js.map +1 -0
- package/packages/web/dist/chapters/index.d.ts +12 -0
- package/packages/web/dist/chapters/index.d.ts.map +1 -0
- package/packages/web/dist/chapters/index.js +8 -0
- package/packages/web/dist/chapters/index.js.map +1 -0
- package/packages/web/dist/chapters/types/ChapterTypes.d.ts +98 -0
- package/packages/web/dist/chapters/types/ChapterTypes.d.ts.map +1 -0
- package/packages/web/dist/chapters/types/ChapterTypes.js +31 -0
- package/packages/web/dist/chapters/types/ChapterTypes.js.map +1 -0
- package/packages/web/dist/index.d.ts +1 -1
- package/packages/web/dist/index.d.ts.map +1 -1
- package/packages/web/dist/index.js +1 -1
- package/packages/web/dist/index.js.map +1 -1
- package/packages/web/dist/paywall/EmailAuthController.d.ts +1 -1
- package/packages/web/dist/paywall/EmailAuthController.d.ts.map +1 -1
- package/packages/web/dist/paywall/PaywallController.d.ts +1 -1
- package/packages/web/dist/paywall/PaywallController.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerView.d.ts +2 -2
- package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
- package/packages/web/dist/react/WebPlayerViewWithEPG.d.ts +2 -2
- package/packages/web/dist/react/WebPlayerViewWithEPG.d.ts.map +1 -1
- package/packages/web/dist/react/components/ChapterProgress.d.ts +22 -0
- package/packages/web/dist/react/components/ChapterProgress.d.ts.map +1 -0
- package/packages/web/dist/react/components/ChapterProgress.js +101 -0
- package/packages/web/dist/react/components/ChapterProgress.js.map +1 -0
- package/packages/web/dist/react/components/SkipButton.d.ts +18 -0
- package/packages/web/dist/react/components/SkipButton.d.ts.map +1 -0
- package/packages/web/dist/react/components/SkipButton.js +156 -0
- package/packages/web/dist/react/components/SkipButton.js.map +1 -0
- package/packages/web/dist/react/hooks/useChapters.d.ts +29 -0
- package/packages/web/dist/react/hooks/useChapters.d.ts.map +1 -0
- package/packages/web/dist/react/hooks/useChapters.js +158 -0
- package/packages/web/dist/react/hooks/useChapters.js.map +1 -0
- package/packages/web/package.json +3 -3
- package/packages/web/src/SecureVideoPlayer.ts +1 -1
- package/packages/web/src/WebPlayer.ts +587 -3
- package/packages/web/src/__tests__/WebPlayer.test.ts +1 -1
- package/packages/web/src/__tests__/epg-integration.test.ts +1 -1
- package/packages/web/src/chapters/ChapterManager.ts +464 -0
- package/packages/web/src/chapters/SkipButtonController.ts +353 -0
- package/packages/web/src/chapters/UserPreferencesManager.ts +324 -0
- package/packages/web/src/chapters/index.ts +34 -0
- package/packages/web/src/chapters/types/ChapterTypes.ts +236 -0
- package/packages/web/src/index.ts +1 -1
- package/packages/web/src/paywall/EmailAuthController.ts +1 -1
- package/packages/web/src/paywall/PaywallController.ts +1 -1
- package/packages/web/src/react/EPG.ts +1 -1
- package/packages/web/src/react/WebPlayerView.tsx +2 -2
- package/packages/web/src/react/WebPlayerViewWithEPG.tsx +3 -3
- package/packages/web/src/react/components/ChapterProgress.tsx +207 -0
- package/packages/web/src/react/components/EPGNavigationControls.tsx +1 -1
- package/packages/web/src/react/components/EPGOverlay-improved-positioning.tsx +1 -1
- package/packages/web/src/react/components/EPGOverlay.tsx +1 -1
- package/packages/web/src/react/components/EPGProgramGrid.tsx +1 -1
- package/packages/web/src/react/components/EPGTimelineHeader.tsx +1 -1
- package/packages/web/src/react/components/SkipButton.tsx +278 -0
- package/packages/web/src/react/hooks/useChapters.ts +308 -0
- package/packages/web/src/react/types/EPGTypes.ts +1 -1
- package/packages/web/src/react/utils/EPGUtils.ts +1 -1
- package/packages/web/src/test/epg-test.ts +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { BasePlayer } from
|
|
1
|
+
import { BasePlayer } from 'unified-video-core';
|
|
2
|
+
import { ChapterManager as CoreChapterManager } from 'unified-video-core';
|
|
3
|
+
import { ChapterManager } from "./chapters/ChapterManager.js";
|
|
2
4
|
export class WebPlayer extends BasePlayer {
|
|
3
5
|
constructor() {
|
|
4
6
|
super(...arguments);
|
|
@@ -50,6 +52,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
50
52
|
this.hasTriedButtonFallback = false;
|
|
51
53
|
this.lastUserInteraction = 0;
|
|
52
54
|
this.showTimeTooltip = false;
|
|
55
|
+
this.chapterManager = null;
|
|
56
|
+
this.coreChapterManager = null;
|
|
57
|
+
this.chapterConfig = { enabled: false };
|
|
53
58
|
}
|
|
54
59
|
debugLog(message, ...args) {
|
|
55
60
|
if (this.config.debug) {
|
|
@@ -85,6 +90,31 @@ export class WebPlayer extends BasePlayer {
|
|
|
85
90
|
else {
|
|
86
91
|
console.log('No settings config found, using defaults:', this.settingsConfig);
|
|
87
92
|
}
|
|
93
|
+
if (config && config.chapters) {
|
|
94
|
+
console.log('Chapter config found:', config.chapters);
|
|
95
|
+
this.chapterConfig = {
|
|
96
|
+
enabled: config.chapters.enabled || false,
|
|
97
|
+
data: config.chapters.data,
|
|
98
|
+
dataUrl: config.chapters.dataUrl,
|
|
99
|
+
autoHide: config.chapters.autoHide !== undefined ? config.chapters.autoHide : true,
|
|
100
|
+
autoHideDelay: config.chapters.autoHideDelay || 5000,
|
|
101
|
+
showChapterMarkers: config.chapters.showChapterMarkers !== undefined ? config.chapters.showChapterMarkers : true,
|
|
102
|
+
skipButtonPosition: config.chapters.skipButtonPosition || 'bottom-right',
|
|
103
|
+
customStyles: config.chapters.customStyles || {},
|
|
104
|
+
userPreferences: config.chapters.userPreferences || {
|
|
105
|
+
autoSkipIntro: false,
|
|
106
|
+
autoSkipRecap: false,
|
|
107
|
+
autoSkipCredits: false,
|
|
108
|
+
showSkipButtons: true,
|
|
109
|
+
skipButtonTimeout: 5000,
|
|
110
|
+
rememberChoices: true
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
console.log('Chapter config applied:', this.chapterConfig);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.log('No chapter config found, chapters disabled');
|
|
117
|
+
}
|
|
88
118
|
await super.initialize(container, config);
|
|
89
119
|
}
|
|
90
120
|
async setupPlayer() {
|
|
@@ -125,6 +155,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
125
155
|
this.setupWatermark();
|
|
126
156
|
this.setupFullscreenListeners();
|
|
127
157
|
this.setupUserInteractionTracking();
|
|
158
|
+
if (this.chapterConfig.enabled && this.video) {
|
|
159
|
+
this.setupChapterManager();
|
|
160
|
+
}
|
|
128
161
|
try {
|
|
129
162
|
const pw = this.config.paywall || null;
|
|
130
163
|
if (pw && pw.enabled) {
|
|
@@ -233,6 +266,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
233
266
|
const t = this.video.currentTime || 0;
|
|
234
267
|
this.updateTime(t);
|
|
235
268
|
this.enforceFreePreviewGate(t);
|
|
269
|
+
if (this.coreChapterManager) {
|
|
270
|
+
this.coreChapterManager.processTimeUpdate(t);
|
|
271
|
+
}
|
|
236
272
|
});
|
|
237
273
|
this.video.addEventListener('progress', () => {
|
|
238
274
|
this.updateBufferProgress();
|
|
@@ -2058,6 +2094,201 @@ export class WebPlayer extends BasePlayer {
|
|
|
2058
2094
|
transform: translateX(-50%) translateY(0);
|
|
2059
2095
|
}
|
|
2060
2096
|
|
|
2097
|
+
/* Chapter Markers */
|
|
2098
|
+
.uvf-chapter-marker {
|
|
2099
|
+
position: absolute;
|
|
2100
|
+
top: 0;
|
|
2101
|
+
width: 2px;
|
|
2102
|
+
height: 100%;
|
|
2103
|
+
background: rgba(255, 255, 255, 0.6);
|
|
2104
|
+
z-index: 4;
|
|
2105
|
+
cursor: pointer;
|
|
2106
|
+
transition: all 0.2s ease;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
.uvf-chapter-marker:hover {
|
|
2110
|
+
width: 3px;
|
|
2111
|
+
box-shadow: 0 0 8px rgba(255, 255, 255, 0.8);
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
.uvf-chapter-marker-intro {
|
|
2115
|
+
background: var(--uvf-accent-1, #ff5722);
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
.uvf-chapter-marker-recap {
|
|
2119
|
+
background: #ffc107;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
.uvf-chapter-marker-credits {
|
|
2123
|
+
background: #9c27b0;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
.uvf-chapter-marker-ad {
|
|
2127
|
+
background: #f44336;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
/* Skip Button Styles */
|
|
2131
|
+
.uvf-skip-button {
|
|
2132
|
+
position: absolute;
|
|
2133
|
+
background: rgba(0, 0, 0, 0.8);
|
|
2134
|
+
color: white;
|
|
2135
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
2136
|
+
border-radius: 8px;
|
|
2137
|
+
padding: 12px 24px;
|
|
2138
|
+
font-size: 16px;
|
|
2139
|
+
font-weight: 600;
|
|
2140
|
+
cursor: pointer;
|
|
2141
|
+
backdrop-filter: blur(10px);
|
|
2142
|
+
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
2143
|
+
z-index: 1000;
|
|
2144
|
+
user-select: none;
|
|
2145
|
+
|
|
2146
|
+
/* Default hidden state */
|
|
2147
|
+
opacity: 0;
|
|
2148
|
+
transform: translateX(100px) scale(0.9);
|
|
2149
|
+
pointer-events: none;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
.uvf-skip-button.visible {
|
|
2153
|
+
opacity: 1;
|
|
2154
|
+
transform: translateX(0) scale(1);
|
|
2155
|
+
pointer-events: auto;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
.uvf-skip-button:hover {
|
|
2159
|
+
background: var(--uvf-accent-1, #ff5722);
|
|
2160
|
+
border-color: var(--uvf-accent-1, #ff5722);
|
|
2161
|
+
transform: translateX(0) scale(1.05);
|
|
2162
|
+
box-shadow: 0 4px 20px rgba(255, 87, 34, 0.4);
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
.uvf-skip-button:active {
|
|
2166
|
+
transform: translateX(0) scale(0.95);
|
|
2167
|
+
transition: all 0.1s ease;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
/* Skip button positioning */
|
|
2171
|
+
.uvf-skip-button-bottom-right {
|
|
2172
|
+
bottom: 100px;
|
|
2173
|
+
right: 30px;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
.uvf-skip-button-bottom-left {
|
|
2177
|
+
bottom: 100px;
|
|
2178
|
+
left: 30px;
|
|
2179
|
+
transform: translateX(-100px) scale(0.9);
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
.uvf-skip-button-bottom-left.visible {
|
|
2183
|
+
transform: translateX(0) scale(1);
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
.uvf-skip-button-bottom-left:hover {
|
|
2187
|
+
transform: translateX(0) scale(1.05);
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
.uvf-skip-button-bottom-left:active {
|
|
2191
|
+
transform: translateX(0) scale(0.95);
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
.uvf-skip-button-top-right {
|
|
2195
|
+
top: 30px;
|
|
2196
|
+
right: 30px;
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
.uvf-skip-button-top-left {
|
|
2200
|
+
top: 30px;
|
|
2201
|
+
left: 30px;
|
|
2202
|
+
transform: translateX(-100px) scale(0.9);
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
.uvf-skip-button-top-left.visible {
|
|
2206
|
+
transform: translateX(0) scale(1);
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
.uvf-skip-button-top-left:hover {
|
|
2210
|
+
transform: translateX(0) scale(1.05);
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
.uvf-skip-button-top-left:active {
|
|
2214
|
+
transform: translateX(0) scale(0.95);
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
/* Skip button segment type styling */
|
|
2218
|
+
.uvf-skip-intro {
|
|
2219
|
+
border-color: var(--uvf-accent-1, #ff5722);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
.uvf-skip-intro:hover {
|
|
2223
|
+
background: var(--uvf-accent-1, #ff5722);
|
|
2224
|
+
border-color: var(--uvf-accent-1, #ff5722);
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
.uvf-skip-recap {
|
|
2228
|
+
border-color: #ffc107;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
.uvf-skip-recap:hover {
|
|
2232
|
+
background: #ffc107;
|
|
2233
|
+
border-color: #ffc107;
|
|
2234
|
+
color: #000;
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
.uvf-skip-credits {
|
|
2238
|
+
border-color: #9c27b0;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
.uvf-skip-credits:hover {
|
|
2242
|
+
background: #9c27b0;
|
|
2243
|
+
border-color: #9c27b0;
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
.uvf-skip-ad {
|
|
2247
|
+
border-color: #f44336;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
.uvf-skip-ad:hover {
|
|
2251
|
+
background: #f44336;
|
|
2252
|
+
border-color: #f44336;
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
/* Auto-skip countdown styling */
|
|
2256
|
+
.uvf-skip-button.auto-skip {
|
|
2257
|
+
position: relative;
|
|
2258
|
+
overflow: hidden;
|
|
2259
|
+
border-color: var(--uvf-accent-1, #ff5722);
|
|
2260
|
+
animation: uvf-skip-pulse 2s infinite;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
.uvf-skip-button.auto-skip::before {
|
|
2264
|
+
content: '';
|
|
2265
|
+
position: absolute;
|
|
2266
|
+
bottom: 0;
|
|
2267
|
+
left: 0;
|
|
2268
|
+
height: 3px;
|
|
2269
|
+
background: var(--uvf-accent-1, #ff5722);
|
|
2270
|
+
width: 0%;
|
|
2271
|
+
transition: none;
|
|
2272
|
+
z-index: -1;
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
.uvf-skip-button.auto-skip.countdown::before {
|
|
2276
|
+
width: 100%;
|
|
2277
|
+
transition: width linear;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
@keyframes uvf-skip-pulse {
|
|
2281
|
+
0% {
|
|
2282
|
+
box-shadow: 0 0 0 0 rgba(255, 87, 34, 0.4);
|
|
2283
|
+
}
|
|
2284
|
+
50% {
|
|
2285
|
+
box-shadow: 0 0 0 8px rgba(255, 87, 34, 0.1);
|
|
2286
|
+
}
|
|
2287
|
+
100% {
|
|
2288
|
+
box-shadow: 0 0 0 0 rgba(255, 87, 34, 0);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2061
2292
|
|
|
2062
2293
|
|
|
2063
2294
|
/* Mobile responsive design with enhanced touch targets */
|
|
@@ -2082,6 +2313,42 @@ export class WebPlayer extends BasePlayer {
|
|
|
2082
2313
|
top: 2.5px; /* Center on the 5px mobile hover progress bar */
|
|
2083
2314
|
}
|
|
2084
2315
|
|
|
2316
|
+
/* Mobile skip button adjustments */
|
|
2317
|
+
.uvf-skip-button {
|
|
2318
|
+
padding: 10px 20px;
|
|
2319
|
+
font-size: 14px;
|
|
2320
|
+
border-radius: 6px;
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
.uvf-skip-button-bottom-right {
|
|
2324
|
+
bottom: 80px;
|
|
2325
|
+
right: 20px;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
.uvf-skip-button-bottom-left {
|
|
2329
|
+
bottom: 80px;
|
|
2330
|
+
left: 20px;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
.uvf-skip-button-top-right {
|
|
2334
|
+
top: 20px;
|
|
2335
|
+
right: 20px;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
.uvf-skip-button-top-left {
|
|
2339
|
+
top: 20px;
|
|
2340
|
+
left: 20px;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
/* Mobile chapter markers */
|
|
2344
|
+
.uvf-chapter-marker {
|
|
2345
|
+
width: 3px; /* Thicker on mobile for better touch */
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
.uvf-chapter-marker:hover {
|
|
2349
|
+
width: 4px;
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2085
2352
|
}
|
|
2086
2353
|
|
|
2087
2354
|
/* Controls Row */
|
|
@@ -5962,6 +6229,202 @@ export class WebPlayer extends BasePlayer {
|
|
|
5962
6229
|
this.setSettingsScrollbarConfig(options);
|
|
5963
6230
|
}
|
|
5964
6231
|
}
|
|
6232
|
+
setupChapterManager() {
|
|
6233
|
+
if (!this.video || !this.playerWrapper) {
|
|
6234
|
+
this.debugWarn('Cannot setup chapter manager: video or wrapper not available');
|
|
6235
|
+
return;
|
|
6236
|
+
}
|
|
6237
|
+
try {
|
|
6238
|
+
this.chapterManager = new ChapterManager(this.playerWrapper, this.video, this.chapterConfig);
|
|
6239
|
+
const coreChapterConfig = {
|
|
6240
|
+
enabled: this.chapterConfig.enabled,
|
|
6241
|
+
chapters: this.convertToChapters(this.chapterConfig.data),
|
|
6242
|
+
segments: this.convertToChapterSegments(this.chapterConfig.data),
|
|
6243
|
+
dataUrl: this.chapterConfig.dataUrl,
|
|
6244
|
+
autoSkip: this.chapterConfig.userPreferences?.autoSkipIntro || false,
|
|
6245
|
+
onChapterChange: (chapter) => {
|
|
6246
|
+
this.debugLog('Core chapter changed:', chapter?.title || 'none');
|
|
6247
|
+
this.emit('chapterchange', chapter);
|
|
6248
|
+
},
|
|
6249
|
+
onSegmentEntered: (segment) => {
|
|
6250
|
+
this.debugLog('Core segment entered:', segment.title);
|
|
6251
|
+
this.emit('segmententered', segment);
|
|
6252
|
+
},
|
|
6253
|
+
onSegmentExited: (segment) => {
|
|
6254
|
+
this.debugLog('Core segment exited:', segment.title);
|
|
6255
|
+
this.emit('segmentexited', segment);
|
|
6256
|
+
},
|
|
6257
|
+
onSegmentSkipped: (segment) => {
|
|
6258
|
+
this.debugLog('Core segment skipped:', segment.title);
|
|
6259
|
+
this.emit('segmentskipped', segment);
|
|
6260
|
+
}
|
|
6261
|
+
};
|
|
6262
|
+
this.coreChapterManager = new CoreChapterManager(coreChapterConfig);
|
|
6263
|
+
this.coreChapterManager.initialize();
|
|
6264
|
+
this.chapterManager.on('segmentEntered', (data) => {
|
|
6265
|
+
this.debugLog('Entered segment:', data.segment.type, data.segment.title);
|
|
6266
|
+
this.emit('chapterSegmentEntered', data);
|
|
6267
|
+
});
|
|
6268
|
+
this.chapterManager.on('segmentSkipped', (data) => {
|
|
6269
|
+
this.debugLog('Skipped segment:', data.fromSegment.type, 'to', data.toSegment?.type || 'end');
|
|
6270
|
+
this.emit('chapterSegmentSkipped', data);
|
|
6271
|
+
});
|
|
6272
|
+
this.chapterManager.on('skipButtonShown', (data) => {
|
|
6273
|
+
this.debugLog('Skip button shown for:', data.segment.type);
|
|
6274
|
+
this.emit('chapterSkipButtonShown', data);
|
|
6275
|
+
});
|
|
6276
|
+
this.chapterManager.on('skipButtonHidden', (data) => {
|
|
6277
|
+
this.debugLog('Skip button hidden for:', data.segment.type, 'reason:', data.reason);
|
|
6278
|
+
this.emit('chapterSkipButtonHidden', data);
|
|
6279
|
+
});
|
|
6280
|
+
this.chapterManager.on('chaptersLoaded', (data) => {
|
|
6281
|
+
this.debugLog('Chapters loaded:', data.segmentCount, 'segments');
|
|
6282
|
+
this.emit('chaptersLoaded', data);
|
|
6283
|
+
});
|
|
6284
|
+
this.chapterManager.on('chaptersLoadError', (data) => {
|
|
6285
|
+
this.debugError('Failed to load chapters:', data.error.message);
|
|
6286
|
+
this.emit('chaptersLoadError', data);
|
|
6287
|
+
});
|
|
6288
|
+
this.debugLog('Chapter managers initialized successfully');
|
|
6289
|
+
}
|
|
6290
|
+
catch (error) {
|
|
6291
|
+
this.debugError('Failed to initialize chapter managers:', error);
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
convertToChapters(webChapterData) {
|
|
6295
|
+
if (!webChapterData || !webChapterData.segments) {
|
|
6296
|
+
return [];
|
|
6297
|
+
}
|
|
6298
|
+
return webChapterData.segments
|
|
6299
|
+
.filter((segment) => segment.type === 'content')
|
|
6300
|
+
.map((segment, index) => ({
|
|
6301
|
+
id: segment.id || `chapter-${index}`,
|
|
6302
|
+
title: segment.title || `Chapter ${index + 1}`,
|
|
6303
|
+
startTime: segment.startTime,
|
|
6304
|
+
endTime: segment.endTime,
|
|
6305
|
+
thumbnail: segment.thumbnail,
|
|
6306
|
+
description: segment.description,
|
|
6307
|
+
metadata: segment.metadata || {}
|
|
6308
|
+
}));
|
|
6309
|
+
}
|
|
6310
|
+
convertToChapterSegments(webChapterData) {
|
|
6311
|
+
if (!webChapterData || !webChapterData.segments) {
|
|
6312
|
+
return [];
|
|
6313
|
+
}
|
|
6314
|
+
return webChapterData.segments
|
|
6315
|
+
.filter((segment) => segment.type !== 'content')
|
|
6316
|
+
.map((segment) => ({
|
|
6317
|
+
id: segment.id,
|
|
6318
|
+
startTime: segment.startTime,
|
|
6319
|
+
endTime: segment.endTime,
|
|
6320
|
+
category: segment.type,
|
|
6321
|
+
action: this.mapSegmentAction(segment.type),
|
|
6322
|
+
title: segment.title,
|
|
6323
|
+
description: segment.description
|
|
6324
|
+
}));
|
|
6325
|
+
}
|
|
6326
|
+
mapSegmentAction(segmentType) {
|
|
6327
|
+
switch (segmentType) {
|
|
6328
|
+
case 'intro':
|
|
6329
|
+
case 'recap':
|
|
6330
|
+
case 'credits':
|
|
6331
|
+
case 'sponsor':
|
|
6332
|
+
return 'skip';
|
|
6333
|
+
case 'offensive':
|
|
6334
|
+
return 'mute';
|
|
6335
|
+
default:
|
|
6336
|
+
return 'warn';
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
async loadChapters(chapters) {
|
|
6340
|
+
if (!this.chapterManager) {
|
|
6341
|
+
throw new Error('Chapter manager not initialized. Enable chapters in config first.');
|
|
6342
|
+
}
|
|
6343
|
+
try {
|
|
6344
|
+
await this.chapterManager.loadChapters(chapters);
|
|
6345
|
+
this.debugLog('Chapters loaded successfully');
|
|
6346
|
+
}
|
|
6347
|
+
catch (error) {
|
|
6348
|
+
this.debugError('Failed to load chapters:', error);
|
|
6349
|
+
throw error;
|
|
6350
|
+
}
|
|
6351
|
+
}
|
|
6352
|
+
async loadChaptersFromUrl(url) {
|
|
6353
|
+
if (!this.chapterManager) {
|
|
6354
|
+
throw new Error('Chapter manager not initialized. Enable chapters in config first.');
|
|
6355
|
+
}
|
|
6356
|
+
try {
|
|
6357
|
+
await this.chapterManager.loadChaptersFromUrl(url);
|
|
6358
|
+
this.debugLog('Chapters loaded from URL successfully');
|
|
6359
|
+
}
|
|
6360
|
+
catch (error) {
|
|
6361
|
+
this.debugError('Failed to load chapters from URL:', error);
|
|
6362
|
+
throw error;
|
|
6363
|
+
}
|
|
6364
|
+
}
|
|
6365
|
+
getCurrentSegment() {
|
|
6366
|
+
if (!this.chapterManager || !this.video) {
|
|
6367
|
+
return null;
|
|
6368
|
+
}
|
|
6369
|
+
return this.chapterManager.getCurrentSegment(this.video.currentTime);
|
|
6370
|
+
}
|
|
6371
|
+
skipToSegment(segmentId) {
|
|
6372
|
+
if (!this.chapterManager) {
|
|
6373
|
+
this.debugWarn('Cannot skip segment: chapter manager not initialized');
|
|
6374
|
+
return;
|
|
6375
|
+
}
|
|
6376
|
+
this.chapterManager.skipToSegment(segmentId);
|
|
6377
|
+
}
|
|
6378
|
+
getSegments() {
|
|
6379
|
+
if (!this.chapterManager) {
|
|
6380
|
+
return [];
|
|
6381
|
+
}
|
|
6382
|
+
return this.chapterManager.getSegments();
|
|
6383
|
+
}
|
|
6384
|
+
updateChapterConfig(newConfig) {
|
|
6385
|
+
this.chapterConfig = { ...this.chapterConfig, ...newConfig };
|
|
6386
|
+
if (this.chapterManager) {
|
|
6387
|
+
this.chapterManager.updateConfig(this.chapterConfig);
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
hasChapters() {
|
|
6391
|
+
return this.chapterManager?.hasChapters() || false;
|
|
6392
|
+
}
|
|
6393
|
+
getChapters() {
|
|
6394
|
+
return this.chapterManager?.getChapters() || null;
|
|
6395
|
+
}
|
|
6396
|
+
getCoreChapters() {
|
|
6397
|
+
return this.coreChapterManager?.getChapters() || [];
|
|
6398
|
+
}
|
|
6399
|
+
getCoreSegments() {
|
|
6400
|
+
return this.coreChapterManager?.getSegments() || [];
|
|
6401
|
+
}
|
|
6402
|
+
getCurrentChapterInfo() {
|
|
6403
|
+
return this.coreChapterManager?.getCurrentChapterInfo() || null;
|
|
6404
|
+
}
|
|
6405
|
+
seekToChapter(chapterId) {
|
|
6406
|
+
if (!this.coreChapterManager || !this.video) {
|
|
6407
|
+
this.debugWarn('Cannot seek to chapter: core chapter manager or video not available');
|
|
6408
|
+
return;
|
|
6409
|
+
}
|
|
6410
|
+
const chapter = this.coreChapterManager.seekToChapter(chapterId);
|
|
6411
|
+
if (chapter) {
|
|
6412
|
+
this.video.currentTime = chapter.startTime;
|
|
6413
|
+
this.debugLog('Seeked to chapter:', chapter.title);
|
|
6414
|
+
}
|
|
6415
|
+
}
|
|
6416
|
+
getNextChapter() {
|
|
6417
|
+
if (!this.coreChapterManager || !this.video) {
|
|
6418
|
+
return null;
|
|
6419
|
+
}
|
|
6420
|
+
return this.coreChapterManager.getNextChapter(this.video.currentTime);
|
|
6421
|
+
}
|
|
6422
|
+
getPreviousChapter() {
|
|
6423
|
+
if (!this.coreChapterManager || !this.video) {
|
|
6424
|
+
return null;
|
|
6425
|
+
}
|
|
6426
|
+
return this.coreChapterManager.getPreviousChapter(this.video.currentTime);
|
|
6427
|
+
}
|
|
5965
6428
|
setTheme(theme) {
|
|
5966
6429
|
const wrapper = this.playerWrapper;
|
|
5967
6430
|
if (!wrapper)
|
|
@@ -7132,6 +7595,14 @@ export class WebPlayer extends BasePlayer {
|
|
|
7132
7595
|
this.paywallController.destroy();
|
|
7133
7596
|
this.paywallController = null;
|
|
7134
7597
|
}
|
|
7598
|
+
if (this.chapterManager && typeof this.chapterManager.destroy === 'function') {
|
|
7599
|
+
this.chapterManager.destroy();
|
|
7600
|
+
this.chapterManager = null;
|
|
7601
|
+
}
|
|
7602
|
+
if (this.coreChapterManager) {
|
|
7603
|
+
this.coreChapterManager.destroy();
|
|
7604
|
+
this.coreChapterManager = null;
|
|
7605
|
+
}
|
|
7135
7606
|
if (this.video) {
|
|
7136
7607
|
this.video.pause();
|
|
7137
7608
|
this.video.removeAttribute('src');
|