@desynova-digital/player 3.9.7 → 4.0.1

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 (130) hide show
  1. package/Player.js +945 -0
  2. package/control/AudioTracksMenuButton.js +91 -0
  3. package/control/AudioTracksMenuButton.jsx +80 -0
  4. package/control/ControlBar.js +303 -0
  5. package/control/ControlBar.jsx +264 -0
  6. package/control/CurrentTimeDisplay.js +34 -0
  7. package/control/CurrentTimeDisplay.jsx +35 -0
  8. package/control/DurationDisplay.js +38 -0
  9. package/control/DurationDisplay.jsx +48 -0
  10. package/control/ForwardBackwardControl.js +76 -0
  11. package/control/ForwardBackwardControl.jsx +79 -0
  12. package/control/FullscreenToggle.js +82 -0
  13. package/control/FullscreenToggle.jsx +83 -0
  14. package/control/MarkInControl.js +124 -0
  15. package/control/MarkInControl.jsx +109 -0
  16. package/control/MarkOutControl.js +137 -0
  17. package/control/MarkOutControl.jsx +131 -0
  18. package/control/MarkerBar.js +127 -0
  19. package/control/MarkerBar.jsx +107 -0
  20. package/control/MarkingControl.js +82 -0
  21. package/control/MarkingControl.jsx +143 -0
  22. package/control/MarkingDuration.js +44 -0
  23. package/control/MarkingPreview.js +49 -0
  24. package/control/MarkingPreview.jsx +60 -0
  25. package/control/PlayBackRateControl.js +106 -0
  26. package/control/PlayBackRateControl.jsx +106 -0
  27. package/control/PlayProgressBar.js +61 -0
  28. package/control/PlayProgressBar.jsx +92 -0
  29. package/control/PlayToggle.js +56 -0
  30. package/control/PlayToggle.jsx +57 -0
  31. package/control/PointersBar.js +231 -0
  32. package/control/PointersBar.jsx +286 -0
  33. package/control/ProgressControl.js +127 -0
  34. package/control/ProgressControl.jsx +155 -0
  35. package/control/SeekBar.js +204 -0
  36. package/control/SeekBar.jsx +229 -0
  37. package/control/SettingsMenuButton.js +63 -0
  38. package/control/SettingsMenuButton.jsx +69 -0
  39. package/control/Slider.js +274 -0
  40. package/control/Slider.jsx +243 -0
  41. package/control/Timeline.js +118 -0
  42. package/control/Timeline.jsx +131 -0
  43. package/control/VolumeBar.js +198 -0
  44. package/control/VolumeBar.jsx +174 -0
  45. package/control/VolumeLevel.js +61 -0
  46. package/control/VolumeLevel.jsx +66 -0
  47. package/control/VolumneMenuButton.js +112 -0
  48. package/control/VolumneMenuButton.jsx +111 -0
  49. package/header/Header.js +309 -0
  50. package/header/Header.jsx +479 -0
  51. package/index.js +9 -151
  52. package/media/AudioMeter.js +381 -0
  53. package/media/AudioMeter.jsx +411 -0
  54. package/media/SDOutline.js +82 -0
  55. package/media/SDOutline.jsx +90 -0
  56. package/media/Video.js +684 -0
  57. package/media/Video.jsx +714 -0
  58. package/package.json +5 -1
  59. package/playlist/Playlist.js +67 -0
  60. package/playlist/Playlist.jsx +91 -0
  61. package/playlist/index.js +13 -0
  62. package/shortcuts/Shortcut.js +662 -0
  63. package/utils/Menu.js +50 -0
  64. package/utils/Menu.jsx +105 -0
  65. package/{colors.js → utils/colors.js} +13 -13
  66. package/utils/dom.js +6 -16
  67. package/utils/index.js +52 -122
  68. package/Manager.js +0 -124
  69. package/actions/player.js +0 -375
  70. package/actions/video.js +0 -230
  71. package/components/AudioMeter.js +0 -414
  72. package/components/BigPlayButton.js +0 -110
  73. package/components/ImageViewer.js +0 -318
  74. package/components/MarkerBar.js +0 -138
  75. package/components/Menu.js +0 -77
  76. package/components/Player.js +0 -821
  77. package/components/PlayerHeader.js +0 -472
  78. package/components/Playlist.js +0 -133
  79. package/components/PointersBar.js +0 -299
  80. package/components/PosterImage.js +0 -61
  81. package/components/SDOutline.js +0 -68
  82. package/components/Shortcut.js +0 -621
  83. package/components/Slider.js +0 -317
  84. package/components/TagsBar.js +0 -100
  85. package/components/Video.js +0 -1431
  86. package/components/control-bar/AudioTracksMenuButton.js +0 -113
  87. package/components/control-bar/CameraButton.js +0 -88
  88. package/components/control-bar/CommentsButton.js +0 -216
  89. package/components/control-bar/ControlBar.js +0 -260
  90. package/components/control-bar/EditorControlMenuButton.js +0 -412
  91. package/components/control-bar/ForwardControl.js +0 -17
  92. package/components/control-bar/ForwardReplayControl.js +0 -122
  93. package/components/control-bar/FullscreenToggle.js +0 -101
  94. package/components/control-bar/PlayToggle.js +0 -98
  95. package/components/control-bar/ReplayControl.js +0 -17
  96. package/components/control-bar/SettingsMenuButton.js +0 -43
  97. package/components/control-bar/SubtitleLanguagesMenuButton.js +0 -174
  98. package/components/control-bar/VolumeMenuButton.js +0 -134
  99. package/components/control-bar/ZoomMenuButton.js +0 -116
  100. package/components/marking-controls/MarkInControl.js +0 -140
  101. package/components/marking-controls/MarkOutControl.js +0 -155
  102. package/components/marking-controls/MarkingAddButton.js +0 -94
  103. package/components/marking-controls/MarkingControl.js +0 -135
  104. package/components/marking-controls/MarkingDeleteButton.js +0 -84
  105. package/components/marking-controls/MarkingDuration.js +0 -77
  106. package/components/marking-controls/MarkingPreview.js +0 -86
  107. package/components/progress-bar/AudioWaveform.js +0 -144
  108. package/components/progress-bar/LoadProgressBar.js +0 -90
  109. package/components/progress-bar/MouseTimeDisplay.js +0 -53
  110. package/components/progress-bar/PlayProgressBar.js +0 -79
  111. package/components/progress-bar/ProgressControl.js +0 -222
  112. package/components/progress-bar/SeekBar.js +0 -261
  113. package/components/progress-bar/Timeline.js +0 -134
  114. package/components/settings-menu-control/PlaybackRateControl.js +0 -147
  115. package/components/settings-menu-control/SafeAreaControl.js +0 -92
  116. package/components/settings-menu-control/SettingsMenu.js +0 -68
  117. package/components/settings-menu-control/SubtitleControl.js +0 -1
  118. package/components/time-controls/CurrentTimeDisplay.js +0 -53
  119. package/components/time-controls/DurationDisplay.js +0 -51
  120. package/components/time-controls/TimeDivider.js +0 -41
  121. package/components/volume-control/VolumeBar.js +0 -216
  122. package/components/volume-control/VolumeControl.js +0 -35
  123. package/components/volume-control/VolumeLevel.js +0 -78
  124. package/components/zoom-control/ZoomBar.js +0 -189
  125. package/components/zoom-control/ZoomLevel.js +0 -68
  126. package/reducers/index.js +0 -23
  127. package/reducers/operation.js +0 -36
  128. package/reducers/player.js +0 -222
  129. package/utils/browser.js +0 -29
  130. package/utils/fullscreen.js +0 -73
@@ -0,0 +1,714 @@
1
+ import { PropTypes } from 'prop-types';
2
+ import React, { Component } from 'react';
3
+ import styled from 'styled-components';
4
+ import Hls from 'hls.js';
5
+ import colors from '../utils/colors';
6
+ import { Button } from '@desynova-digital/components';
7
+ // import Manager from '../Manager';
8
+ // import { mergeAndSortChildren, isVideoChild, mediaProperties, throttle } from '../utils';
9
+ // import BigPlayButton from './BigPlayButton';
10
+ // import PosterImage from './PosterImage';
11
+ // import SDOutline from './SDOutline';
12
+ import { Loader } from '@desynova-digital/components/components';
13
+ import SDOutline from './SDOutline';
14
+ import AudioMeter from './AudioMeter';
15
+
16
+ const propTypes = {
17
+ actions: PropTypes.instanceOf(Object),
18
+ player: PropTypes.instanceOf(Object),
19
+ startTime: PropTypes.number,
20
+ loop: PropTypes.bool,
21
+ muted: PropTypes.bool,
22
+ autoPlay: PropTypes.bool,
23
+ playsInline: PropTypes.bool,
24
+ src: PropTypes.string,
25
+ poster: PropTypes.string,
26
+ className: PropTypes.string,
27
+ fileType: PropTypes.oneOf(['video', 'image', 'audio']),
28
+ preload: PropTypes.oneOf(['auto', 'metadata', 'none']),
29
+ crossOrigin: PropTypes.string,
30
+ fluid: PropTypes.bool,
31
+ children: PropTypes.arrayOf(PropTypes.element),
32
+ store: PropTypes.instanceOf(Object),
33
+ width: PropTypes.number,
34
+ activeTrackIndex: PropTypes.number,
35
+ height: PropTypes.number,
36
+ videoId: PropTypes.string,
37
+ onLoadStart: PropTypes.func,
38
+ onWaiting: PropTypes.func,
39
+ onCanPlay: PropTypes.func,
40
+ onCanPlayThrough: PropTypes.func,
41
+ onPlaying: PropTypes.func,
42
+ onEnded: PropTypes.func,
43
+ onSeeking: PropTypes.func,
44
+ onSeeked: PropTypes.func,
45
+ onPlay: PropTypes.func,
46
+ onPause: PropTypes.func,
47
+ onProgress: PropTypes.func,
48
+ onDurationChange: PropTypes.func,
49
+ onError: PropTypes.func,
50
+ onSuspend: PropTypes.func,
51
+ onAbort: PropTypes.func,
52
+ onEmptied: PropTypes.func,
53
+ onStalled: PropTypes.func,
54
+ onLoadedMetadata: PropTypes.func,
55
+ onLoadedData: PropTypes.func,
56
+ onTimeUpdate: PropTypes.func,
57
+ onRateChange: PropTypes.func,
58
+ onVolumeChange: PropTypes.func,
59
+ onResize: PropTypes.func,
60
+ aspectRatio: PropTypes.string,
61
+ onPlayerClose: PropTypes.func,
62
+ userEmail: PropTypes.string,
63
+ playerSelectedMarker: PropTypes.instanceOf(Object)
64
+ };
65
+
66
+ const defaultProps = {
67
+ startTime: 0,
68
+ loop: false,
69
+ muted: false,
70
+ autoPlay: false,
71
+ playsInline: false,
72
+ preload: 'auto',
73
+ aspectRatio: 'auto',
74
+ crossOrigin: 'anonymous'
75
+ };
76
+
77
+ const SubTitleSection = styled.div`
78
+ position: absolute;
79
+ font-family: SFUIText-Regular;
80
+ font-size: 16px;
81
+ bottom: 20px;
82
+ width: 100%;
83
+ display: flex;
84
+ justify-content: center;
85
+ text-align: center;
86
+ color: #ffffff;
87
+ height: 90%;
88
+ align-items: center;
89
+
90
+ .subtitleContainer {
91
+ border-radius: 4px;
92
+ width: fit-content;
93
+ background: #000000;
94
+ opacity: 0.9;
95
+ padding: 8px 10px;
96
+ line-height: 20px;
97
+ position: absolute;
98
+ }
99
+ `;
100
+
101
+ const VideoBlock = styled.div`
102
+ position: relative;
103
+ &.video-react-player-block {
104
+ position: relative;
105
+ transition: all 0.1s ease-in-out;
106
+ -moz-transition: all 0.1s ease-in-out;
107
+ -webkit-transition: all 0.1s ease-in-out;
108
+ -ms-transition: all 0.1s ease-in-out;
109
+ -o-transition: all 0.1s ease-in-out;
110
+ video {
111
+ position: absolute;
112
+ top: 0;
113
+ left: 0;
114
+ width: 100%;
115
+ height: 100%;
116
+ right: 0;
117
+ bottom: 0;
118
+ }
119
+ .audio-tracks {
120
+ position: relative;
121
+ display: flex;
122
+ background: rgba(0, 0, 0, 0.5);
123
+ color: #fff;
124
+ z-index: 10;
125
+ position: absolute;
126
+ width: 100%;
127
+ bottom: 0;
128
+ p {
129
+ cursor: pointer;
130
+ padding: 10px;
131
+ }
132
+ }
133
+ .loader-container {
134
+ width: 100%;
135
+ height: 100%;
136
+ display: flex;
137
+ justify-content: center;
138
+ align-items: center;
139
+ position: absolute;
140
+ z-index: 10;
141
+ background: rgba(0, 0, 0, 0.5);
142
+ }
143
+ }
144
+ &.ratio-border {
145
+ border: 1px solid rgba(255, 255, 255, 0.5);
146
+ &:after {
147
+ content: '16:9 Safe Area';
148
+ position: absolute;
149
+ color: #fff;
150
+ font-family: SFUIText-Regular;
151
+ font-size: 12px;
152
+ transform: rotate(-90deg);
153
+ top: 20%;
154
+ left: -50px;
155
+ }
156
+ }
157
+ `;
158
+ const PlayButton = styled(Button)`
159
+ background: ${(props) => colors.common.video[props.assetType].buttonGradient};
160
+ width: 100px;
161
+ height: 100px;
162
+ position: absolute;
163
+ top: 50%;
164
+ left: 50%;
165
+ transform: translate(-50%, -50%);
166
+ border: none;
167
+ z-index: 1;
168
+ &:hover,
169
+ &:focus {
170
+ background: ${(props) => colors.common.video[props.assetType].buttonGradient};
171
+ }
172
+ `;
173
+
174
+ const AudioMeterBlock = styled('div')`
175
+ width: ${(props) => (!props.active ? '50px' : '55px')};
176
+ height: ${(props) => (!props.active ? '50px !important' : 'calc(100% - 80px)')};
177
+ position: absolute;
178
+ bottom: ${(props) => (!props.active ? '5px' : '0px')};
179
+ right: 15px;
180
+ padding: ${(props) => (!props.active ? '5px' : '0px')};
181
+ box-sizing: border-box;
182
+ background: ${(props) => (!props.active ? 'rgba(243, 243, 243, 0.5)' : 'rgba(0, 0, 0, 1)')};
183
+ border-radius: ${(props) => (!props.active ? '5px' : '0px')};
184
+ display: ${(props) => (!props.active ? 'block' : 'inline-block')};
185
+ margin: ${(props) => (!props.active ? '0' : '20px 0')};
186
+ transition: all 0.1s ease-in-out;
187
+ -moz-transition: all 0.1s ease-in-out;
188
+ -webkit-transition: all 0.1s ease-in-out;
189
+ -ms-transition: all 0.1s ease-in-out;
190
+ -o-transition: all 0.1s ease-in-out;
191
+ `;
192
+
193
+ export default class Video extends Component {
194
+ constructor(props) {
195
+ super(props);
196
+ this.state = {
197
+ audioTracks: [],
198
+ isM3U8: false,
199
+ watermark: {
200
+ color: 'rgb(255, 255, 255)',
201
+ position: 'absolute',
202
+ 'font-family': 'SFUIText-Regular',
203
+ 'text-shadow': '0 0 4px rgb(0 0 0 / 50%)',
204
+ 'font-size': '12px',
205
+ opacity: '0.6',
206
+ display: 'block',
207
+ top: '0px',
208
+ left: '0px'
209
+ },
210
+ watermarkInterval: -1,
211
+ isBuffering: false,
212
+ currentSubtitleObj: {}
213
+ };
214
+ this.video = null; // the html5 video
215
+ // this.manager = new Manager(props.store);
216
+ this.play = this.play.bind(this);
217
+ this.pause = this.pause.bind(this);
218
+ this.seek = this.seek.bind(this);
219
+ this.forward = this.forward.bind(this);
220
+ this.replay = this.replay.bind(this);
221
+ this.toggleFullscreen = this.toggleFullscreen.bind(this);
222
+ this.handleEnded = this.handleEnded.bind(this);
223
+ this.handleLoadedMetaData = this.handleLoadedMetaData.bind(this);
224
+ this.handleTimeUpdate = this.handleTimeUpdate.bind(this);
225
+ this.checkWatermark = this.checkWatermark.bind(this);
226
+ }
227
+
228
+ componentDidMount() {
229
+ const { src } = this.props;
230
+ const isM3U8 = src.split('.').pop() === 'm3u8' ? true : false;
231
+ this.setState({
232
+ isM3U8: isM3U8
233
+ });
234
+ if (Hls.isSupported() && isM3U8) {
235
+ const { HLSConfig } = this.props;
236
+ this.hls = new Hls(HLSConfig);
237
+ this.setupHLS(src);
238
+ } else {
239
+ this.video.src = src;
240
+ }
241
+ // this.forceUpdate(); // make sure the children can get the video property
242
+ const watermarkInterval = setInterval(this.checkWatermark, 20000);
243
+ this.setState({
244
+ watermarkInterval: watermarkInterval
245
+ });
246
+ }
247
+
248
+ componentWillUnmount() {
249
+ const { isM3U8, watermarkInterval } = this.state;
250
+ if (Hls.isSupported() && isM3U8) {
251
+ this.hls.detachMedia();
252
+ } else {
253
+ this.video.src = '';
254
+ }
255
+ clearInterval(watermarkInterval);
256
+ }
257
+
258
+ /**
259
+ * This function is triggered on interval to shuffle the position of watermark on Player area
260
+ */
261
+ checkWatermark() {
262
+ const { watermark } = this.state;
263
+ const { onPlayerClose, userEmail } = this.props;
264
+ const watermark_text = document.querySelector('#watermark-text');
265
+ let video_player = null;
266
+ let watermark_dimension = null;
267
+ let text_css = null;
268
+ let bool_text = false;
269
+
270
+ if (!watermark_text) {
271
+ onPlayerClose();
272
+ } else {
273
+ video_player = document.querySelector('.video-react-player-block').getBoundingClientRect();
274
+ watermark_dimension = watermark_text.getBoundingClientRect();
275
+ text_css = watermark_text.style;
276
+ bool_text =
277
+ text_css.position !== 'absolute' ||
278
+ text_css.opacity !== '0.6' ||
279
+ (text_css['font-family'] !== 'SFUIText-Regular' && text_css['font-family'] !== '"SFUIText-Regular"');
280
+ bool_text = bool_text || text_css.display !== 'block';
281
+ bool_text = bool_text || text_css.top !== watermark.top;
282
+ bool_text = bool_text || text_css.left !== watermark.left;
283
+ bool_text = bool_text || text_css.length !== 9 || text_css['font-size'] !== '12px';
284
+ bool_text = bool_text || text_css.color !== 'rgb(255, 255, 255)';
285
+ bool_text = bool_text || userEmail !== watermark_text.innerText;
286
+ if (bool_text) {
287
+ onPlayerClose();
288
+ }
289
+ }
290
+ watermark.left = (Math.random() * (video_player.width - watermark_dimension.width)).toFixed(0) + 'px';
291
+ watermark.top = (Math.random() * (video_player.height - watermark_dimension.height)).toFixed(0) + 'px';
292
+ this.setState({
293
+ watermark: watermark
294
+ });
295
+ }
296
+
297
+ setupHLS(src) {
298
+ const { actions, activeTrackIndex, actionClick } = this.props;
299
+ const self = this;
300
+ // bind them together
301
+ this.hls.attachMedia(this.video);
302
+ this.hls.on(Hls.Events.MEDIA_ATTACHED, function() {
303
+ self.hls.loadSource(src);
304
+ });
305
+ this.hls.on(Hls.Events.MANIFEST_PARSED, function(event, data) {
306
+ let trackIndex = activeTrackIndex || 0;
307
+ //todo handle below actions and merge it into same setstate.
308
+ actionClick({
309
+ action: 'handle_audio_tracks',
310
+ value: data.audioTracks
311
+ });
312
+ actionClick({
313
+ action: 'handle_audio_track_change',
314
+ value: data.audioTracks[trackIndex]
315
+ });
316
+ });
317
+ this.hls.on(Hls.Events.ERROR, (event, data) => {
318
+ // eslint-disable-next-line no-console
319
+ console.log('HLS.Events.ERROR: ', event, data);
320
+ if (data.fatal) {
321
+ switch (data.type) {
322
+ case Hls.ErrorTypes.NETWORK_ERROR:
323
+ // try to recover network error
324
+ this.hls.startLoad();
325
+ break;
326
+ case Hls.ErrorTypes.MEDIA_ERROR:
327
+ this.hls.recoverMediaError();
328
+ break;
329
+ default:
330
+ // cannot recover
331
+ this.hls.destroy();
332
+ break;
333
+ }
334
+ } else if (data.details === 'internalException' && data.type === 'otherError') {
335
+ this.hls.startLoad();
336
+ }
337
+ });
338
+ }
339
+
340
+ UNSAFE_componentWillReceiveProps(newProps) {
341
+ const {
342
+ src,
343
+ // player: { activeAudio },
344
+ currentSubtitleObj,
345
+ markers
346
+ } = this.props;
347
+ if (newProps.src !== src) {
348
+ const { isM3U8 } = this.state;
349
+ if (Hls.isSupported() && isM3U8 && this.hls.media) {
350
+ this.hls.detachMedia();
351
+ } else {
352
+ this.video.src = '';
353
+ }
354
+ setTimeout(() => {
355
+ const m3u8 = newProps.src.split('.').pop() === 'm3u8' ? true : false;
356
+ this.setState({
357
+ isM3U8: m3u8
358
+ });
359
+ if (Hls.isSupported() && m3u8) {
360
+ const { HLSConfig } = this.props;
361
+ this.hls = new Hls(HLSConfig);
362
+ this.setupHLS(newProps.src);
363
+ } else {
364
+ this.video.src = newProps.src;
365
+ }
366
+ this.forceUpdate();
367
+ }, 0); // make sure the children can get the video property
368
+ }
369
+ // if (newProps.player.activeAudio && activeAudio && activeAudio.id !== newProps.player.activeAudio.id) {
370
+ // this.hls.audioTrack = newProps.player.activeAudio.id;
371
+ // }
372
+ if (
373
+ newProps.subtitleObj &&
374
+ newProps.subtitleObj.field &&
375
+ JSON.stringify(newProps.subtitleObj) !== JSON.stringify(currentSubtitleObj)
376
+ ) {
377
+ if (newProps.subtitleObj && newProps.subtitleObj.field && !newProps.subtitleObj.field.line1) {
378
+ this.setState({
379
+ currentSubtitleObj: {}
380
+ });
381
+ } else if (newProps.subtitleObj && newProps.subtitleObj.field && newProps.subtitleObj.field.line1) {
382
+ const style = this.getSubtitleStyle(newProps.subtitleObj.field);
383
+ this.setState({
384
+ currentSubtitleObj: {
385
+ line1: newProps.subtitleObj.field.line1,
386
+ line2: newProps.subtitleObj.field.line2,
387
+ start_time: newProps.subtitleObj.field.in_time,
388
+ end_time: newProps.subtitleObj.field.out_time,
389
+ style
390
+ }
391
+ });
392
+ }
393
+ }
394
+ if (newProps.markers.length && markers.length && newProps.markers[0].values.length !== markers[0].values.length) {
395
+ this.displaySubtitle(newProps.markers);
396
+ }
397
+ if (newProps.subtitleReadOnly && newProps.subtitleDataList) {
398
+ this.displaySubtitle(newProps.subtitleDataList);
399
+ }
400
+ }
401
+
402
+ // play the video
403
+ play() {
404
+ const promise = this.video.play();
405
+ if (promise !== undefined) {
406
+ promise.catch(() => {}).then(() => {});
407
+ }
408
+ }
409
+
410
+ // pause the video
411
+ pause() {
412
+ const promise = this.video.pause();
413
+ if (promise !== undefined) {
414
+ promise.catch(() => {}).then(() => {});
415
+ }
416
+ }
417
+
418
+ // Change the video source and re-load the video:
419
+ load() {
420
+ this.video.load();
421
+ }
422
+
423
+ // Add a new text track to the video
424
+ addTextTrack(...args) {
425
+ this.video.addTextTrack(...args);
426
+ }
427
+
428
+ // Check if your browser can play different types of video:
429
+ canPlayType(...args) {
430
+ this.video.canPlayType(...args);
431
+ }
432
+
433
+ // toggle play
434
+ togglePlay() {
435
+ if (this.video.paused) {
436
+ this.play();
437
+ } else {
438
+ this.pause();
439
+ }
440
+ }
441
+
442
+ // seek video by time
443
+ seek(time) {
444
+ try {
445
+ this.video.currentTime = time;
446
+ } catch (e) {
447
+ // console.log(e, 'Video is not ready.')
448
+ }
449
+ }
450
+
451
+ // jump forward x seconds
452
+ forward(seconds) {
453
+ this.seek(this.video.currentTime + seconds);
454
+ }
455
+
456
+ // jump back x seconds
457
+ replay(seconds) {
458
+ this.forward(-seconds);
459
+ }
460
+
461
+ // enter or exist full screen
462
+ toggleFullscreen() {
463
+ const { player, actions } = this.props;
464
+ actions.toggleFullscreen(player);
465
+ }
466
+
467
+ getSubtitleStyle(data) {
468
+ const style = {};
469
+ style.top = data && data.text_position === 'text_position_top' ? '0px' : '';
470
+ style.bottom = data && data.text_position === 'text_position_bottom' ? '0px' : '';
471
+ style.left = data && data.text_alignment === 'text_aligned_left' ? '0px' : '';
472
+ style.right = data && data.text_alignment === 'text_aligned_right' ? '0px' : '';
473
+ return style;
474
+ }
475
+
476
+ displaySubtitle(marker) {
477
+ const { markers, resetSubtitleData, subtitleReadOnly, subtitleDataList } = this.props;
478
+ const { currentSubtitleObj } = this.state;
479
+ if (resetSubtitleData) {
480
+ resetSubtitleData();
481
+ }
482
+ const currentTime = this.video.currentTime;
483
+ let currentMarker = marker || markers;
484
+ if (subtitleReadOnly) {
485
+ currentMarker = marker || subtitleDataList;
486
+ }
487
+ if (currentMarker && currentMarker[0] && currentMarker[0].name === 'Subtitle') {
488
+ const values = currentMarker[0].values;
489
+ const currentValue = values.filter((ele) => ele.start_time <= currentTime && ele.end_time >= currentTime);
490
+ const style = this.getSubtitleStyle(currentValue[0]);
491
+ const currentLine1 = (currentSubtitleObj && currentSubtitleObj.line1) || '';
492
+ const propsLine1 = (currentValue[0] && currentValue[0].line1) || '';
493
+ if (
494
+ (currentValue &&
495
+ currentValue.length &&
496
+ (currentSubtitleObj.start_time === currentValue[0].start_time ||
497
+ currentSubtitleObj.end_time === currentValue[0].end_time) &&
498
+ currentLine1 === propsLine1) ||
499
+ (Object.keys(currentSubtitleObj).length &&
500
+ currentValue.length &&
501
+ currentValue.length === currentSubtitleObj.start_time.length &&
502
+ currentValue.length === currentSubtitleObj.end_time.length &&
503
+ currentLine1 === propsLine1)
504
+ ) {
505
+ return;
506
+ } else {
507
+ this.setState({
508
+ currentSubtitleObj: {
509
+ line1: (currentValue[0] && currentValue[0].line1) || '',
510
+ line2: (currentValue[0] && currentValue[0].line2) || '',
511
+ start_time: (currentValue[0] && currentValue[0].start_time) || 0,
512
+ end_time: (currentValue[0] && currentValue[0].end_time) || 0,
513
+ style
514
+ }
515
+ });
516
+ }
517
+ }
518
+ }
519
+
520
+ /*
521
+ * Fired when the end of the media resource
522
+ * is reached (currentTime == duration)
523
+ */
524
+ handleEnded(...args) {
525
+ const { loop, player, actions, onEnded } = this.props;
526
+ if (loop) {
527
+ this.seek(0);
528
+ this.play();
529
+ } else if (!player.paused) {
530
+ this.pause();
531
+ }
532
+ actions.handleEnd(this.getProperties());
533
+
534
+ if (onEnded) {
535
+ onEnded(...args);
536
+ }
537
+ }
538
+
539
+ /*
540
+ * Fires when the browser has loaded
541
+ * meta data for the audio/video
542
+ */
543
+ handleLoadedMetaData = () => {
544
+ const { actionClick } = this.props;
545
+ actionClick({
546
+ action: 'handle_loaded_meta_data',
547
+ value: this.video.duration
548
+ });
549
+ };
550
+
551
+ handleSubtitleContainerClick() {
552
+ const { actionClick, paused } = this.props;
553
+ if (paused) {
554
+ actionClick({
555
+ action: 'play'
556
+ });
557
+ } else {
558
+ actionClick({
559
+ action: 'pause'
560
+ });
561
+ }
562
+ }
563
+
564
+ handleSubtitleClick(e) {
565
+ const { actionClick, paused, onScreenSubtitleClick, controlType } = this.props;
566
+ const { currentSubtitleObj } = this.state;
567
+ if (controlType === 'advanced') {
568
+ if (onScreenSubtitleClick) {
569
+ onScreenSubtitleClick(currentSubtitleObj);
570
+ }
571
+ actionClick({
572
+ action: 'pause'
573
+ });
574
+ } else {
575
+ if (paused) {
576
+ actionClick({
577
+ action: 'play'
578
+ });
579
+ } else {
580
+ actionClick({
581
+ action: 'pause'
582
+ });
583
+ }
584
+ }
585
+ // actions.handleVideoRewind(false);
586
+ e.stopPropagation();
587
+ }
588
+
589
+ /*
590
+ * Fires when the current
591
+ * playback position has changed
592
+ */
593
+ handleTimeUpdate = () => {
594
+ const {
595
+ actionClick,
596
+ previewActive,
597
+ playerSelectedMarker: { rightMarker }
598
+ } = this.props;
599
+ if (previewActive && this.video.currentTime >= rightMarker) {
600
+ actionClick({
601
+ action: 'pause'
602
+ });
603
+ actionClick({
604
+ action: 'seek',
605
+ value: rightMarker
606
+ });
607
+ actionClick({
608
+ action: 'handle_video_preview',
609
+ value: false
610
+ });
611
+ }
612
+ actionClick({
613
+ action: 'handle_time_update',
614
+ value: this.video.currentTime
615
+ });
616
+ this.displaySubtitle();
617
+ };
618
+
619
+ render() {
620
+ const { crossOrigin, videoId, userEmail, SDBorderActive, actionClick, paused } = this.props;
621
+
622
+ const { isBuffering, watermark, currentSubtitleObj } = this.state;
623
+
624
+ // const children = this.getChildren(this.props);
625
+ return (
626
+ <>
627
+ <VideoBlock
628
+ className="video-react-player-block"
629
+ id="media-container"
630
+ ref={(c) => {
631
+ this.playerBlock = c;
632
+ }}
633
+ // style={this.getStyle()}
634
+ >
635
+ {/* {(isBuffering && (
636
+ <div className="loader-container" onClick={() => this.togglePlay()}>
637
+ <Loader loaderName="SpinningLoader" />
638
+ </div>
639
+ )) ||
640
+ null} */}
641
+ <video
642
+ id={videoId}
643
+ // crossOrigin={crossOrigin}
644
+ src={this.props.src}
645
+ ref={(c) => {
646
+ this.video = c;
647
+ }}
648
+ onPlay={() => {
649
+ actionClick({
650
+ action: 'play'
651
+ });
652
+ }}
653
+ onPause={() => {
654
+ actionClick({
655
+ action: 'pause'
656
+ });
657
+ }}
658
+ onLoadedMetadata={this.handleLoadedMetaData}
659
+ onTimeUpdate={this.handleTimeUpdate}>
660
+ <track kind="captions" />
661
+ </video>
662
+ {paused && (
663
+ <PlayButton
664
+ display="rounded"
665
+ appearance="cta"
666
+ icon="play"
667
+ iconWidth={20}
668
+ iconHeight={26}
669
+ width={100}
670
+ height={100}
671
+ tabIndex="0"
672
+ onClick={() => {
673
+ actionClick({
674
+ action: 'play'
675
+ });
676
+ }}
677
+ {...this.props}
678
+ />
679
+ )}
680
+ <SDOutline SDBorderActive={SDBorderActive} actionClick={actionClick} paused={paused} />
681
+ {/* {children} */}
682
+ <p className="user-name-wrapper" id="watermark-text" style={{ ...watermark }}>
683
+ {userEmail}
684
+ </p>
685
+ {currentSubtitleObj && currentSubtitleObj.line1 && currentSubtitleObj.line1.length && (
686
+ <SubTitleSection id="outer" onClick={() => this.handleSubtitleContainerClick()}>
687
+ <span
688
+ onClick={(e) => this.handleSubtitleClick(e)}
689
+ className="subtitleContainer"
690
+ style={{ ...currentSubtitleObj.style }}>
691
+ {(currentSubtitleObj.line1 && <pre> {currentSubtitleObj.line1} </pre>) || null}
692
+ {(currentSubtitleObj.line2 && <pre> {currentSubtitleObj.line2} </pre>) || null}
693
+ </span>
694
+ </SubTitleSection>
695
+ )}
696
+ </VideoBlock>
697
+ </>
698
+ );
699
+ // <AudioMeterBlock
700
+ // id="audio-meter-block"
701
+ // onClick={() => {
702
+ // this.meterBlockClick();
703
+ // }}
704
+ // role="presentation"
705
+ // active>
706
+ // {/* <AudioMeter player={props.player} height={this.meterHeight} /> */}
707
+ // <AudioMeter height="40" {...this.props} />
708
+ // </AudioMeterBlock>
709
+ }
710
+ }
711
+
712
+ Video.propTypes = propTypes;
713
+ Video.defaultProps = defaultProps;
714
+ Video.displayName = 'Video';