unified-video-framework 1.4.151 → 1.4.154

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.
Files changed (86) hide show
  1. package/package.json +1 -1
  2. package/packages/core/dist/chapter-manager.d.ts +39 -0
  3. package/packages/core/dist/chapter-manager.d.ts.map +1 -0
  4. package/packages/core/dist/chapter-manager.js +173 -0
  5. package/packages/core/dist/chapter-manager.js.map +1 -0
  6. package/packages/core/dist/index.d.ts +2 -0
  7. package/packages/core/dist/index.d.ts.map +1 -1
  8. package/packages/core/dist/index.js +1 -0
  9. package/packages/core/dist/index.js.map +1 -1
  10. package/packages/core/dist/interfaces/IVideoPlayer.d.ts +10 -0
  11. package/packages/core/dist/interfaces/IVideoPlayer.d.ts.map +1 -1
  12. package/packages/core/dist/interfaces.d.ts +33 -1
  13. package/packages/core/dist/interfaces.d.ts.map +1 -1
  14. package/packages/core/src/chapter-manager.ts +290 -0
  15. package/packages/core/src/index.ts +4 -0
  16. package/packages/core/src/interfaces/IVideoPlayer.ts +11 -0
  17. package/packages/core/src/interfaces.ts +47 -1
  18. package/packages/web/dist/WebPlayer.d.ts +24 -1
  19. package/packages/web/dist/WebPlayer.d.ts.map +1 -1
  20. package/packages/web/dist/WebPlayer.js +472 -1
  21. package/packages/web/dist/WebPlayer.js.map +1 -1
  22. package/packages/web/dist/chapters/ChapterManager.d.ts +38 -0
  23. package/packages/web/dist/chapters/ChapterManager.d.ts.map +1 -0
  24. package/packages/web/dist/chapters/ChapterManager.js +291 -0
  25. package/packages/web/dist/chapters/ChapterManager.js.map +1 -0
  26. package/packages/web/dist/chapters/SkipButtonController.d.ts +31 -0
  27. package/packages/web/dist/chapters/SkipButtonController.d.ts.map +1 -0
  28. package/packages/web/dist/chapters/SkipButtonController.js +213 -0
  29. package/packages/web/dist/chapters/SkipButtonController.js.map +1 -0
  30. package/packages/web/dist/chapters/UserPreferencesManager.d.ts +25 -0
  31. package/packages/web/dist/chapters/UserPreferencesManager.d.ts.map +1 -0
  32. package/packages/web/dist/chapters/UserPreferencesManager.js +232 -0
  33. package/packages/web/dist/chapters/UserPreferencesManager.js.map +1 -0
  34. package/packages/web/dist/chapters/index.d.ts +12 -0
  35. package/packages/web/dist/chapters/index.d.ts.map +1 -0
  36. package/packages/web/dist/chapters/index.js +8 -0
  37. package/packages/web/dist/chapters/index.js.map +1 -0
  38. package/packages/web/dist/chapters/types/ChapterTypes.d.ts +98 -0
  39. package/packages/web/dist/chapters/types/ChapterTypes.d.ts.map +1 -0
  40. package/packages/web/dist/chapters/types/ChapterTypes.js +31 -0
  41. package/packages/web/dist/chapters/types/ChapterTypes.js.map +1 -0
  42. package/packages/web/dist/index.d.ts +1 -1
  43. package/packages/web/dist/index.d.ts.map +1 -1
  44. package/packages/web/dist/index.js +1 -1
  45. package/packages/web/dist/index.js.map +1 -1
  46. package/packages/web/dist/react/WebPlayerView.d.ts +2 -2
  47. package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
  48. package/packages/web/dist/react/WebPlayerViewWithEPG.d.ts +2 -2
  49. package/packages/web/dist/react/WebPlayerViewWithEPG.d.ts.map +1 -1
  50. package/packages/web/dist/react/components/ChapterProgress.d.ts +22 -0
  51. package/packages/web/dist/react/components/ChapterProgress.d.ts.map +1 -0
  52. package/packages/web/dist/react/components/ChapterProgress.js +101 -0
  53. package/packages/web/dist/react/components/ChapterProgress.js.map +1 -0
  54. package/packages/web/dist/react/components/SkipButton.d.ts +18 -0
  55. package/packages/web/dist/react/components/SkipButton.d.ts.map +1 -0
  56. package/packages/web/dist/react/components/SkipButton.js +156 -0
  57. package/packages/web/dist/react/components/SkipButton.js.map +1 -0
  58. package/packages/web/dist/react/hooks/useChapters.d.ts +29 -0
  59. package/packages/web/dist/react/hooks/useChapters.d.ts.map +1 -0
  60. package/packages/web/dist/react/hooks/useChapters.js +158 -0
  61. package/packages/web/dist/react/hooks/useChapters.js.map +1 -0
  62. package/packages/web/package.json +0 -3
  63. package/packages/web/src/SecureVideoPlayer.ts +1 -1
  64. package/packages/web/src/WebPlayer.ts +587 -3
  65. package/packages/web/src/__tests__/WebPlayer.test.ts +1 -1
  66. package/packages/web/src/__tests__/epg-integration.test.ts +1 -1
  67. package/packages/web/src/chapters/ChapterManager.ts +464 -0
  68. package/packages/web/src/chapters/SkipButtonController.ts +353 -0
  69. package/packages/web/src/chapters/UserPreferencesManager.ts +324 -0
  70. package/packages/web/src/chapters/index.ts +34 -0
  71. package/packages/web/src/chapters/types/ChapterTypes.ts +236 -0
  72. package/packages/web/src/index.ts +1 -1
  73. package/packages/web/src/react/EPG.ts +1 -1
  74. package/packages/web/src/react/WebPlayerView.tsx +2 -2
  75. package/packages/web/src/react/WebPlayerViewWithEPG.tsx +3 -3
  76. package/packages/web/src/react/components/ChapterProgress.tsx +207 -0
  77. package/packages/web/src/react/components/EPGNavigationControls.tsx +1 -1
  78. package/packages/web/src/react/components/EPGOverlay-improved-positioning.tsx +1 -1
  79. package/packages/web/src/react/components/EPGOverlay.tsx +1 -1
  80. package/packages/web/src/react/components/EPGProgramGrid.tsx +1 -1
  81. package/packages/web/src/react/components/EPGTimelineHeader.tsx +1 -1
  82. package/packages/web/src/react/components/SkipButton.tsx +278 -0
  83. package/packages/web/src/react/hooks/useChapters.ts +308 -0
  84. package/packages/web/src/react/types/EPGTypes.ts +1 -1
  85. package/packages/web/src/react/utils/EPGUtils.ts +1 -1
  86. package/packages/web/src/test/epg-test.ts +1 -1
@@ -1,4 +1,6 @@
1
- import { BasePlayer } from "../../core/dist/index.js";
1
+ import { BasePlayer } from "../../core/src/BasePlayer.js";
2
+ import { ChapterManager as CoreChapterManager } from "../../core/src/index.js";
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');