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
@@ -0,0 +1,101 @@
1
+ import React, { useMemo } from 'react';
2
+ import { SEGMENT_COLORS } from "../../chapters/types/ChapterTypes.js";
3
+ export const ChapterProgress = ({ chapters, progress = 0, buffered = 0, showMarkers = true, markerColors = {}, onMarkerClick, onProgressClick, className = '', style = {}, interactive = true }) => {
4
+ const markers = useMemo(() => {
5
+ if (!chapters || !showMarkers)
6
+ return [];
7
+ const colors = { ...SEGMENT_COLORS, ...markerColors };
8
+ return chapters.segments
9
+ .filter(segment => segment.type !== 'content')
10
+ .map(segment => ({
11
+ segment,
12
+ position: (segment.startTime / chapters.duration) * 100,
13
+ color: colors[segment.type] || '#ffffff',
14
+ label: segment.title || segment.type
15
+ }))
16
+ .sort((a, b) => a.position - b.position);
17
+ }, [chapters, showMarkers, markerColors]);
18
+ const handleProgressClick = (event) => {
19
+ if (!interactive || !onProgressClick)
20
+ return;
21
+ const rect = event.currentTarget.getBoundingClientRect();
22
+ const x = event.clientX - rect.left;
23
+ const percentage = (x / rect.width) * 100;
24
+ onProgressClick(Math.max(0, Math.min(100, percentage)));
25
+ };
26
+ const handleMarkerClick = (event, segment) => {
27
+ event.stopPropagation();
28
+ onMarkerClick?.(segment);
29
+ };
30
+ const progressClasses = [
31
+ 'uvf-chapter-progress',
32
+ interactive ? 'interactive' : '',
33
+ className
34
+ ].filter(Boolean).join(' ');
35
+ return (React.createElement("div", { className: progressClasses, style: {
36
+ position: 'relative',
37
+ width: '100%',
38
+ height: '4px',
39
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
40
+ borderRadius: '2px',
41
+ cursor: interactive ? 'pointer' : 'default',
42
+ ...style
43
+ }, onClick: handleProgressClick },
44
+ React.createElement("div", { className: "uvf-chapter-progress-buffered", style: {
45
+ position: 'absolute',
46
+ top: 0,
47
+ left: 0,
48
+ height: '100%',
49
+ width: `${Math.max(0, Math.min(100, buffered))}%`,
50
+ backgroundColor: 'rgba(255, 255, 255, 0.4)',
51
+ borderRadius: 'inherit',
52
+ transition: 'width 0.3s ease'
53
+ } }),
54
+ React.createElement("div", { className: "uvf-chapter-progress-current", style: {
55
+ position: 'absolute',
56
+ top: 0,
57
+ left: 0,
58
+ height: '100%',
59
+ width: `${Math.max(0, Math.min(100, progress))}%`,
60
+ background: 'linear-gradient(90deg, var(--uvf-accent-1, #ff5722) 0%, var(--uvf-accent-2, #ff8a50) 100%)',
61
+ borderRadius: 'inherit',
62
+ transition: 'width 0.1s ease'
63
+ } }),
64
+ markers.map((marker, index) => (React.createElement("div", { key: `${marker.segment.id}-${index}`, className: `uvf-chapter-progress-marker uvf-marker-${marker.segment.type}`, style: {
65
+ position: 'absolute',
66
+ top: '50%',
67
+ left: `${marker.position}%`,
68
+ width: '3px',
69
+ height: '150%',
70
+ backgroundColor: marker.color,
71
+ transform: 'translate(-50%, -50%)',
72
+ cursor: 'pointer',
73
+ borderRadius: '1px',
74
+ zIndex: 10,
75
+ transition: 'all 0.2s ease'
76
+ }, title: `${marker.label} (${formatTime(marker.segment.startTime)})`, onClick: (e) => handleMarkerClick(e, marker.segment), onMouseEnter: (e) => {
77
+ const element = e.currentTarget;
78
+ element.style.width = '4px';
79
+ element.style.height = '200%';
80
+ element.style.boxShadow = `0 0 8px ${marker.color}`;
81
+ }, onMouseLeave: (e) => {
82
+ const element = e.currentTarget;
83
+ element.style.width = '3px';
84
+ element.style.height = '150%';
85
+ element.style.boxShadow = 'none';
86
+ } })))));
87
+ };
88
+ function formatTime(seconds) {
89
+ if (!seconds || isNaN(seconds))
90
+ return '0:00';
91
+ const hours = Math.floor(seconds / 3600);
92
+ const minutes = Math.floor((seconds % 3600) / 60);
93
+ const secs = Math.floor(seconds % 60);
94
+ if (hours > 0) {
95
+ return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
96
+ }
97
+ else {
98
+ return `${minutes}:${secs.toString().padStart(2, '0')}`;
99
+ }
100
+ }
101
+ //# sourceMappingURL=ChapterProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChapterProgress.js","sourceRoot":"","sources":["../../../src/react/components/ChapterProgress.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAGL,cAAc,EACf,MAAM,mCAAmC,CAAC;AAyC3C,MAAM,CAAC,MAAM,eAAe,GAAmC,CAAC,EAC9D,QAAQ,EACR,QAAQ,GAAG,CAAC,EACZ,QAAQ,GAAG,CAAC,EACZ,WAAW,GAAG,IAAI,EAClB,YAAY,GAAG,EAAE,EACjB,aAAa,EACb,eAAe,EACf,SAAS,GAAG,EAAE,EACd,KAAK,GAAG,EAAE,EACV,WAAW,GAAG,IAAI,EACnB,EAAE,EAAE;IAIH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAoB,EAAE;QAC5C,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAEzC,MAAM,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,YAAY,EAAE,CAAC;QAEtD,OAAO,QAAQ,CAAC,QAAQ;aACrB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;aAC7C,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACf,OAAO;YACP,QAAQ,EAAE,CAAC,OAAO,CAAC,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG;YACvD,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS;YACxC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI;SACrC,CAAC,CAAC;aACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAK1C,MAAM,mBAAmB,GAAG,CAAC,KAAuC,EAAE,EAAE;QACtE,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe;YAAE,OAAO;QAE7C,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,qBAAqB,EAAE,CAAC;QACzD,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QACpC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;QAE1C,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC;IAKF,MAAM,iBAAiB,GAAG,CAAC,KAAuB,EAAE,OAAqB,EAAE,EAAE;QAC3E,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,aAAa,EAAE,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;IAGF,MAAM,eAAe,GAAG;QACtB,sBAAsB;QACtB,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE;QAChC,SAAS;KACV,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE5B,OAAO,CACL,6BACE,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,KAAK;YACb,eAAe,EAAE,0BAA0B;YAC3C,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC3C,GAAG,KAAK;SACT,EACD,OAAO,EAAE,mBAAmB;QAG5B,6BACE,SAAS,EAAC,+BAA+B,EACzC,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,CAAC;gBACN,IAAI,EAAE,CAAC;gBACP,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG;gBACjD,eAAe,EAAE,0BAA0B;gBAC3C,YAAY,EAAE,SAAS;gBACvB,UAAU,EAAE,iBAAiB;aAC9B,GACD;QAGF,6BACE,SAAS,EAAC,8BAA8B,EACxC,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,CAAC;gBACN,IAAI,EAAE,CAAC;gBACP,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG;gBACjD,UAAU,EAAE,4FAA4F;gBACxG,YAAY,EAAE,SAAS;gBACvB,UAAU,EAAE,iBAAiB;aAC9B,GACD;QAGD,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAC9B,6BACE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,EAAE,EACpC,SAAS,EAAE,0CAA0C,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAC1E,KAAK,EAAE;gBACL,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG;gBAC3B,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,MAAM;gBACd,eAAe,EAAE,MAAM,CAAC,KAAK;gBAC7B,SAAS,EAAE,uBAAuB;gBAClC,MAAM,EAAE,SAAS;gBACjB,YAAY,EAAE,KAAK;gBACnB,MAAM,EAAE,EAAE;gBACV,UAAU,EAAE,eAAe;aAC5B,EACD,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAClE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,EACpD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;gBAClB,MAAM,OAAO,GAAG,CAAC,CAAC,aAA4B,CAAC;gBAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC5B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,WAAW,MAAM,CAAC,KAAK,EAAE,CAAC;YACtD,CAAC,EACD,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;gBAClB,MAAM,OAAO,GAAG,CAAC,CAAC,aAA4B,CAAC;gBAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC5B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;YACnC,CAAC,GACD,CACH,CAAC,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AAKF,SAAS,UAAU,CAAC,OAAe;IACjC,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IAEtC,IAAI,KAAK,GAAG,CAAC,EAAE;QACb,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;KAC9F;SAAM;QACL,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;KACzD;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { VideoSegment, SkipButtonPosition } from '../../chapters/types/ChapterTypes';
3
+ export interface SkipButtonProps {
4
+ segment: VideoSegment | null;
5
+ visible?: boolean;
6
+ position?: SkipButtonPosition;
7
+ autoHideDelay?: number;
8
+ skipLabel?: string;
9
+ onSkip?: (segment: VideoSegment) => void;
10
+ onShow?: (segment: VideoSegment) => void;
11
+ onHide?: (segment: VideoSegment, reason: string) => void;
12
+ className?: string;
13
+ style?: React.CSSProperties;
14
+ enableAutoSkip?: boolean;
15
+ autoSkipDelay?: number;
16
+ }
17
+ export declare const SkipButton: React.FC<SkipButtonProps>;
18
+ //# sourceMappingURL=SkipButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkipButton.d.ts","sourceRoot":"","sources":["../../../src/react/components/SkipButton.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,kBAAkB,EAEnB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,eAAe;IAE9B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAG7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAG9B,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAGzC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAGzC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAGzD,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAG5B,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAoOhD,CAAC"}
@@ -0,0 +1,156 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { DEFAULT_SKIP_LABELS } from "../../chapters/types/ChapterTypes.js";
3
+ export const SkipButton = ({ segment, visible = false, position = 'bottom-right', autoHideDelay = 5000, skipLabel, onSkip, onShow, onHide, className = '', style = {}, enableAutoSkip = false, autoSkipDelay = 10 }) => {
4
+ const [isVisible, setIsVisible] = useState(visible);
5
+ const [isAutoSkip, setIsAutoSkip] = useState(false);
6
+ const [countdown, setCountdown] = useState(null);
7
+ const autoHideTimeoutRef = useRef(null);
8
+ const autoSkipTimeoutRef = useRef(null);
9
+ const countdownIntervalRef = useRef(null);
10
+ const previousSegmentRef = useRef(null);
11
+ const clearTimeouts = () => {
12
+ if (autoHideTimeoutRef.current) {
13
+ clearTimeout(autoHideTimeoutRef.current);
14
+ autoHideTimeoutRef.current = null;
15
+ }
16
+ if (autoSkipTimeoutRef.current) {
17
+ clearTimeout(autoSkipTimeoutRef.current);
18
+ autoSkipTimeoutRef.current = null;
19
+ }
20
+ if (countdownIntervalRef.current) {
21
+ clearInterval(countdownIntervalRef.current);
22
+ countdownIntervalRef.current = null;
23
+ }
24
+ };
25
+ const startAutoSkip = (segment, delay) => {
26
+ setIsAutoSkip(true);
27
+ setCountdown(delay);
28
+ countdownIntervalRef.current = setInterval(() => {
29
+ setCountdown((prev) => {
30
+ if (prev === null || prev <= 1) {
31
+ clearTimeouts();
32
+ onSkip?.(segment);
33
+ handleHide('timeout');
34
+ return null;
35
+ }
36
+ return prev - 1;
37
+ });
38
+ }, 1000);
39
+ autoSkipTimeoutRef.current = setTimeout(() => {
40
+ clearTimeouts();
41
+ onSkip?.(segment);
42
+ handleHide('timeout');
43
+ }, delay * 1000);
44
+ };
45
+ const handleSkip = () => {
46
+ if (!segment)
47
+ return;
48
+ clearTimeouts();
49
+ onSkip?.(segment);
50
+ handleHide('user-action');
51
+ };
52
+ const handleShow = () => {
53
+ if (!segment)
54
+ return;
55
+ setIsVisible(true);
56
+ onShow?.(segment);
57
+ if (autoHideDelay > 0) {
58
+ autoHideTimeoutRef.current = setTimeout(() => {
59
+ handleHide('timeout');
60
+ }, autoHideDelay);
61
+ }
62
+ if (enableAutoSkip && segment.autoSkip && segment.autoSkipDelay) {
63
+ startAutoSkip(segment, segment.autoSkipDelay);
64
+ }
65
+ };
66
+ const handleHide = (reason = 'manual') => {
67
+ if (!segment)
68
+ return;
69
+ clearTimeouts();
70
+ setIsVisible(false);
71
+ setIsAutoSkip(false);
72
+ setCountdown(null);
73
+ onHide?.(segment, reason);
74
+ };
75
+ useEffect(() => {
76
+ if (visible && segment && segment !== previousSegmentRef.current) {
77
+ previousSegmentRef.current = segment;
78
+ handleShow();
79
+ }
80
+ else if (!visible || !segment) {
81
+ if (previousSegmentRef.current) {
82
+ handleHide('segment-end');
83
+ }
84
+ previousSegmentRef.current = null;
85
+ }
86
+ }, [visible, segment]);
87
+ useEffect(() => {
88
+ return () => {
89
+ clearTimeouts();
90
+ };
91
+ }, []);
92
+ if (!segment || !isVisible) {
93
+ return null;
94
+ }
95
+ const buttonText = skipLabel || segment.skipLabel || DEFAULT_SKIP_LABELS[segment.type];
96
+ const displayText = isAutoSkip && countdown !== null
97
+ ? `${buttonText} (${countdown})`
98
+ : buttonText;
99
+ const positionClass = `uvf-skip-button-${position}`;
100
+ const segmentClass = `uvf-skip-${segment.type}`;
101
+ const autoSkipClass = isAutoSkip ? 'auto-skip' : '';
102
+ const countdownClass = isAutoSkip && countdown !== null ? 'countdown' : '';
103
+ const buttonClasses = [
104
+ 'uvf-skip-button',
105
+ 'visible',
106
+ positionClass,
107
+ segmentClass,
108
+ autoSkipClass,
109
+ countdownClass,
110
+ className
111
+ ].filter(Boolean).join(' ');
112
+ const defaultStyles = {
113
+ position: 'absolute',
114
+ zIndex: 1000,
115
+ ...style
116
+ };
117
+ switch (position) {
118
+ case 'bottom-right':
119
+ Object.assign(defaultStyles, {
120
+ bottom: '100px',
121
+ right: '30px'
122
+ });
123
+ break;
124
+ case 'bottom-left':
125
+ Object.assign(defaultStyles, {
126
+ bottom: '100px',
127
+ left: '30px'
128
+ });
129
+ break;
130
+ case 'top-right':
131
+ Object.assign(defaultStyles, {
132
+ top: '30px',
133
+ right: '30px'
134
+ });
135
+ break;
136
+ case 'top-left':
137
+ Object.assign(defaultStyles, {
138
+ top: '30px',
139
+ left: '30px'
140
+ });
141
+ break;
142
+ }
143
+ return (React.createElement("button", { type: "button", className: buttonClasses, style: defaultStyles, onClick: handleSkip, "aria-label": `${buttonText} - ${segment.title || segment.type}` },
144
+ displayText,
145
+ isAutoSkip && countdown !== null && (React.createElement("div", { className: "uvf-skip-countdown-progress", style: {
146
+ position: 'absolute',
147
+ bottom: 0,
148
+ left: 0,
149
+ height: '3px',
150
+ backgroundColor: 'currentColor',
151
+ width: `${((autoSkipDelay - countdown) / autoSkipDelay) * 100}%`,
152
+ transition: 'width 1s linear',
153
+ borderRadius: '0 0 6px 6px'
154
+ } }))));
155
+ };
156
+ //# sourceMappingURL=SkipButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkipButton.js","sourceRoot":"","sources":["../../../src/react/components/SkipButton.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { VideoSegment, VideoChapters, ChapterConfig, SegmentType } from '../../chapters/types/ChapterTypes';
2
+ export interface UseChaptersOptions {
3
+ videoElement?: HTMLVideoElement | null;
4
+ chapters?: VideoChapters;
5
+ config?: ChapterConfig;
6
+ onSegmentEntered?: (segment: VideoSegment) => void;
7
+ onSegmentSkipped?: (fromSegment: VideoSegment, toSegment?: VideoSegment) => void;
8
+ onSkipButtonShown?: (segment: VideoSegment) => void;
9
+ onSkipButtonHidden?: (segment: VideoSegment) => void;
10
+ }
11
+ export interface UseChaptersResult {
12
+ currentSegment: VideoSegment | null;
13
+ chapters: VideoChapters | null;
14
+ isSkipButtonVisible: boolean;
15
+ loadChapters: (chapters: VideoChapters) => Promise<void>;
16
+ skipToSegment: (segmentId: string) => void;
17
+ skipCurrentSegment: () => void;
18
+ getSegmentsByType: (type: SegmentType) => VideoSegment[];
19
+ hasSegmentType: (type: SegmentType) => boolean;
20
+ getChapterMarkers: () => Array<{
21
+ position: number;
22
+ segment: VideoSegment;
23
+ color: string;
24
+ }>;
25
+ formatTime: (seconds: number) => string;
26
+ isInSegment: (segmentId: string) => boolean;
27
+ }
28
+ export declare function useChapters(options?: UseChaptersOptions): UseChaptersResult;
29
+ //# sourceMappingURL=useChapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChapters.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useChapters.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EAEb,WAAW,EACZ,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;IACjF,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACpD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,iBAAiB;IAEhC,cAAc,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAG7B,YAAY,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAG/B,iBAAiB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,YAAY,EAAE,CAAC;IACzD,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC;IAC/C,iBAAiB,EAAE,MAAM,KAAK,CAAC;QAC7B,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,YAAY,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IAGH,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7C;AAED,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CAmQ/E"}
@@ -0,0 +1,158 @@
1
+ import { useState, useEffect, useCallback, useRef } from 'react';
2
+ export function useChapters(options = {}) {
3
+ const { videoElement, chapters: initialChapters, config = { enabled: true }, onSegmentEntered, onSegmentSkipped, onSkipButtonShown, onSkipButtonHidden } = options;
4
+ const [currentSegment, setCurrentSegment] = useState(null);
5
+ const [chapters, setChapters] = useState(initialChapters || null);
6
+ const [isSkipButtonVisible, setIsSkipButtonVisible] = useState(false);
7
+ const timeUpdateHandlerRef = useRef(null);
8
+ const previousSegmentRef = useRef(null);
9
+ const getCurrentSegment = useCallback((currentTime) => {
10
+ if (!chapters)
11
+ return null;
12
+ return chapters.segments.find(segment => currentTime >= segment.startTime && currentTime < segment.endTime) || null;
13
+ }, [chapters]);
14
+ const handleTimeUpdate = useCallback(() => {
15
+ if (!videoElement || !chapters)
16
+ return;
17
+ const newSegment = getCurrentSegment(videoElement.currentTime);
18
+ if (newSegment !== currentSegment) {
19
+ if (currentSegment) {
20
+ setIsSkipButtonVisible(false);
21
+ onSkipButtonHidden?.(currentSegment);
22
+ }
23
+ previousSegmentRef.current = currentSegment;
24
+ setCurrentSegment(newSegment);
25
+ if (newSegment) {
26
+ onSegmentEntered?.(newSegment);
27
+ if (shouldShowSkipButton(newSegment)) {
28
+ setIsSkipButtonVisible(true);
29
+ onSkipButtonShown?.(newSegment);
30
+ }
31
+ }
32
+ }
33
+ }, [videoElement, chapters, currentSegment, onSegmentEntered, onSkipButtonShown, onSkipButtonHidden, getCurrentSegment]);
34
+ const shouldShowSkipButton = useCallback((segment) => {
35
+ if (!config.userPreferences?.showSkipButtons) {
36
+ return false;
37
+ }
38
+ if (segment.type === 'content') {
39
+ return segment.showSkipButton === true;
40
+ }
41
+ return segment.showSkipButton !== false;
42
+ }, [config]);
43
+ useEffect(() => {
44
+ if (!videoElement)
45
+ return;
46
+ const handler = () => handleTimeUpdate();
47
+ timeUpdateHandlerRef.current = handler;
48
+ videoElement.addEventListener('timeupdate', handler);
49
+ return () => {
50
+ videoElement.removeEventListener('timeupdate', handler);
51
+ };
52
+ }, [videoElement, handleTimeUpdate]);
53
+ const loadChapters = useCallback(async (newChapters) => {
54
+ if (!newChapters.videoId || !newChapters.duration || !Array.isArray(newChapters.segments)) {
55
+ throw new Error('Invalid chapters data');
56
+ }
57
+ const sortedChapters = {
58
+ ...newChapters,
59
+ segments: [...newChapters.segments].sort((a, b) => a.startTime - b.startTime)
60
+ };
61
+ setChapters(sortedChapters);
62
+ if (videoElement) {
63
+ const segment = getCurrentSegment(videoElement.currentTime);
64
+ setCurrentSegment(segment);
65
+ }
66
+ }, [videoElement, getCurrentSegment]);
67
+ const skipToSegment = useCallback((segmentId) => {
68
+ if (!chapters || !videoElement)
69
+ return;
70
+ const segment = chapters.segments.find(s => s.id === segmentId);
71
+ if (!segment)
72
+ return;
73
+ const fromSegment = currentSegment;
74
+ if (fromSegment) {
75
+ onSegmentSkipped?.(fromSegment, segment);
76
+ }
77
+ videoElement.currentTime = segment.startTime;
78
+ }, [chapters, videoElement, currentSegment, onSegmentSkipped]);
79
+ const skipCurrentSegment = useCallback(() => {
80
+ if (!currentSegment || !chapters || !videoElement)
81
+ return;
82
+ const sortedSegments = [...chapters.segments].sort((a, b) => a.startTime - b.startTime);
83
+ const currentIndex = sortedSegments.findIndex(s => s.id === currentSegment.id);
84
+ if (currentIndex === -1)
85
+ return;
86
+ let nextSegment;
87
+ for (let i = currentIndex + 1; i < sortedSegments.length; i++) {
88
+ if (sortedSegments[i].type === 'content') {
89
+ nextSegment = sortedSegments[i];
90
+ break;
91
+ }
92
+ }
93
+ const targetTime = nextSegment ? nextSegment.startTime : currentSegment.endTime;
94
+ onSegmentSkipped?.(currentSegment, nextSegment);
95
+ videoElement.currentTime = targetTime;
96
+ }, [currentSegment, chapters, videoElement, onSegmentSkipped]);
97
+ const getSegmentsByType = useCallback((type) => {
98
+ if (!chapters)
99
+ return [];
100
+ return chapters.segments.filter(segment => segment.type === type);
101
+ }, [chapters]);
102
+ const hasSegmentType = useCallback((type) => {
103
+ return getSegmentsByType(type).length > 0;
104
+ }, [getSegmentsByType]);
105
+ const getChapterMarkers = useCallback(() => {
106
+ if (!chapters)
107
+ return [];
108
+ const segmentColors = {
109
+ intro: '#ff5722',
110
+ recap: '#ffc107',
111
+ content: '#4caf50',
112
+ credits: '#9c27b0',
113
+ ad: '#f44336'
114
+ };
115
+ return chapters.segments
116
+ .filter(segment => segment.type !== 'content')
117
+ .map(segment => ({
118
+ position: (segment.startTime / chapters.duration) * 100,
119
+ segment,
120
+ color: segmentColors[segment.type]
121
+ }));
122
+ }, [chapters]);
123
+ const formatTime = useCallback((seconds) => {
124
+ if (!seconds || isNaN(seconds))
125
+ return '00:00';
126
+ const hours = Math.floor(seconds / 3600);
127
+ const minutes = Math.floor((seconds % 3600) / 60);
128
+ const secs = Math.floor(seconds % 60);
129
+ if (hours > 0) {
130
+ return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
131
+ }
132
+ else {
133
+ return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
134
+ }
135
+ }, []);
136
+ const isInSegment = useCallback((segmentId) => {
137
+ return currentSegment?.id === segmentId;
138
+ }, [currentSegment]);
139
+ useEffect(() => {
140
+ if (initialChapters) {
141
+ loadChapters(initialChapters);
142
+ }
143
+ }, [initialChapters, loadChapters]);
144
+ return {
145
+ currentSegment,
146
+ chapters,
147
+ isSkipButtonVisible,
148
+ loadChapters,
149
+ skipToSegment,
150
+ skipCurrentSegment,
151
+ getSegmentsByType,
152
+ hasSegmentType,
153
+ getChapterMarkers,
154
+ formatTime,
155
+ isInSegment
156
+ };
157
+ }
158
+ //# sourceMappingURL=useChapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChapters.js","sourceRoot":"","sources":["../../../src/react/hooks/useChapters.ts"],"names":[],"mappings":"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"}
@@ -15,9 +15,6 @@
15
15
  "test": "jest",
16
16
  "lint": "eslint src --ext .ts,.tsx,.js"
17
17
  },
18
- "dependencies": {
19
- "@unified-video/core": "file:../core"
20
- },
21
18
  "peerDependencies": {
22
19
  "dashjs": "^4.0.0",
23
20
  "hls.js": "^1.0.0",
@@ -8,7 +8,7 @@ import {
8
8
  PlayerConfig,
9
9
  PlayerError,
10
10
  Quality
11
- } from '@unified-video/core';
11
+ } from '../../core/src';
12
12
 
13
13
  // Extended configuration for secure player
14
14
  export interface SecurePlayerConfig {