ravnur-player-public 3.4.4 → 3.4.6

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 (260) hide show
  1. package/dist/RavnurMediaPlayer.min.js +1 -1
  2. package/dist/cdn/RavnurMediaPlayer.min.js +1 -1
  3. package/package.json +72 -68
  4. package/.eslintignore +0 -7
  5. package/.eslintrc.js +0 -206
  6. package/.flowconfig +0 -3
  7. package/.vscode/extensions.json +0 -7
  8. package/.vscode/launch.json +0 -37
  9. package/.vscode/settings.json +0 -4
  10. package/README-Private.md +0 -54
  11. package/babel.config.js +0 -28
  12. package/bitbucket-pipelines.yml +0 -61
  13. package/cert.pem +0 -23
  14. package/demo/BaseM.mp4 +0 -0
  15. package/demo/HD.mp4 +0 -0
  16. package/demo/annotations.json +0 -50
  17. package/demo/annotations_ge.json +0 -50
  18. package/demo/base.mp3 +0 -0
  19. package/demo/cc_2125en.vtt +0 -4958
  20. package/demo/cc_en.vtt +0 -171
  21. package/demo/cc_ge.vtt +0 -178
  22. package/demo/chapters_en.vtt +0 -38
  23. package/demo/chapters_ge.vtt +0 -5
  24. package/demo/chapters_ge1.json +0 -23
  25. package/demo/hls/audio/stereo/en/128kbit.m3u8 +0 -912
  26. package/demo/hls/audio/stereo/none/128kbit.m3u8 +0 -912
  27. package/demo/hls/audio/surround/en/320kbit.m3u8 +0 -912
  28. package/demo/hls/playlist.m3u8 +0 -31
  29. package/demo/hls/video/10000kbit.m3u8 +0 -894
  30. package/demo/hls/video/1100kbit.m3u8 +0 -894
  31. package/demo/hls/video/1500kbit.m3u8 +0 -894
  32. package/demo/hls/video/250kbit.m3u8 +0 -894
  33. package/demo/hls/video/4000kbit.m3u8 +0 -894
  34. package/demo/hls/video/500kbit.m3u8 +0 -894
  35. package/demo/hls/video/6000kbit.m3u8 +0 -894
  36. package/demo/hls/video/800kbit.m3u8 +0 -894
  37. package/demo/hls.js +0 -5
  38. package/demo/hls.js.map +0 -1
  39. package/demo/hls.min.js +0 -2
  40. package/demo/hls.min.js.map +0 -1
  41. package/demo/playlist.m3u8 +0 -31
  42. package/demo/ravnur-flash-audio.swf +0 -0
  43. package/demo/ravnur-flash-video-hls.swf +0 -0
  44. package/demo/ravnur-flash-video.swf +0 -0
  45. package/demo/shaka/shaka-player.foo.debug.d.ts +0 -4532
  46. package/demo/shaka/shaka-player.foo.debug.externs.js +0 -3886
  47. package/demo/shaka/shaka-player.foo.debug.js +0 -1746
  48. package/demo/shaka/shaka-player.foo.debug.map +0 -8
  49. package/demo/shaka/wrapper.js +0 -7
  50. package/demo/test.html +0 -458
  51. package/jest.config.js +0 -4
  52. package/key.pem +0 -27
  53. package/lib/es5.js +0 -344
  54. package/lib/images/Spinner-small.gif +0 -0
  55. package/lib/images/close.png +0 -0
  56. package/lib/images/ic_check_box_black_24dp_1x.png +0 -0
  57. package/lib/images/ic_check_box_outline_blank_black_24dp_1x.png +0 -0
  58. package/lib/images/ic_chevron_left_white_24dp_1x.png +0 -0
  59. package/lib/images/ic_chevron_right_white_24dp_1x.png +0 -0
  60. package/lib/images/ic_closed_caption_white_24dp_1x.png +0 -0
  61. package/lib/images/ic_fast_forward_white_24dp_1x.png +0 -0
  62. package/lib/images/ic_fast_rewind_white_24dp_1x.png +0 -0
  63. package/lib/images/ic_fullscreen_exit_white_24dp_1x.png +0 -0
  64. package/lib/images/ic_fullscreen_white_24dp_1x.png +0 -0
  65. package/lib/images/ic_hd_white_24dp_1x.png +0 -0
  66. package/lib/images/ic_keyboard_arrow_left_black_24dp_1x.png +0 -0
  67. package/lib/images/ic_keyboard_arrow_right_black_24dp_1x.png +0 -0
  68. package/lib/images/ic_pause_white_24dp_1x.png +0 -0
  69. package/lib/images/ic_photo_white_24dp_1x.png +0 -0
  70. package/lib/images/ic_play_arrow_white_24dp_1x.png +0 -0
  71. package/lib/images/ic_refresh_white_24dp_1x.png +0 -0
  72. package/lib/images/ic_settings_white_24dp_1x.png +0 -0
  73. package/lib/images/ic_skip_next_white_24dp_1x.png +0 -0
  74. package/lib/images/ic_skip_previous_white_24dp_1x.png +0 -0
  75. package/lib/images/ic_toc_white_24dp_1x.png +0 -0
  76. package/lib/images/ic_volume_off_white_24dp_1x.png +0 -0
  77. package/lib/images/ic_volume_up_white_24dp_1x.png +0 -0
  78. package/lib/player4ie8.css +0 -225
  79. package/server.js +0 -29
  80. package/src/config/cc.js +0 -56
  81. package/src/config/i18n.js +0 -101
  82. package/src/config/options.js +0 -123
  83. package/src/config/playlist.js +0 -9
  84. package/src/config/source.js +0 -23
  85. package/src/config/statuses.js +0 -8
  86. package/src/config/styles.js +0 -16
  87. package/src/entity.js +0 -27
  88. package/src/events.js +0 -5
  89. package/src/extensions/annotations.js +0 -142
  90. package/src/extensions/audio-tarcks.js +0 -115
  91. package/src/extensions/backward.js +0 -45
  92. package/src/extensions/base.js +0 -73
  93. package/src/extensions/bottom-next.js +0 -50
  94. package/src/extensions/bottom-prev.js +0 -50
  95. package/src/extensions/buffering.js +0 -78
  96. package/src/extensions/c2pa.js +0 -350
  97. package/src/extensions/caption-search.js +0 -230
  98. package/src/extensions/cc.js +0 -874
  99. package/src/extensions/crawl.js +0 -118
  100. package/src/extensions/download.js +0 -411
  101. package/src/extensions/error.js +0 -47
  102. package/src/extensions/forward.js +0 -44
  103. package/src/extensions/fullscreen.js +0 -84
  104. package/src/extensions/help.js +0 -201
  105. package/src/extensions/helpers/FileSaver.js +0 -157
  106. package/src/extensions/helpers/clickOpener.js +0 -180
  107. package/src/extensions/helpers/opener.js +0 -30
  108. package/src/extensions/helpers/openerHeightChecker.js +0 -13
  109. package/src/extensions/helpers/popover.js +0 -33
  110. package/src/extensions/helpers/popoverPosition.js +0 -30
  111. package/src/extensions/helpers/scrollIntoView.js +0 -9
  112. package/src/extensions/helpers/storage.js +0 -20
  113. package/src/extensions/helpers/textContent.js +0 -6
  114. package/src/extensions/helpers/timeCodeToSeconds.js +0 -44
  115. package/src/extensions/helpers/transport.js +0 -43
  116. package/src/extensions/helpers/vtt-loader.js +0 -42
  117. package/src/extensions/index.js +0 -87
  118. package/src/extensions/live.js +0 -76
  119. package/src/extensions/mux.js +0 -57
  120. package/src/extensions/next-frame.js +0 -44
  121. package/src/extensions/next.js +0 -48
  122. package/src/extensions/placeholder.js +0 -241
  123. package/src/extensions/play.js +0 -102
  124. package/src/extensions/poster.js +0 -47
  125. package/src/extensions/prev-frame.js +0 -44
  126. package/src/extensions/prev.js +0 -48
  127. package/src/extensions/progress.js +0 -465
  128. package/src/extensions/resizer.js +0 -37
  129. package/src/extensions/settings.js +0 -367
  130. package/src/extensions/theater.js +0 -56
  131. package/src/extensions/title.js +0 -38
  132. package/src/extensions/toc.js +0 -334
  133. package/src/extensions/volume.js +0 -196
  134. package/src/flash/FlashPlugin.js +0 -301
  135. package/src/flash/MediaElement.js +0 -361
  136. package/src/flash/plugins.js +0 -32
  137. package/src/flash-detector.js +0 -66
  138. package/src/helpers/$t.js +0 -10
  139. package/src/helpers/binder.js +0 -11
  140. package/src/helpers/isAndroid.js +0 -5
  141. package/src/helpers/isBlackBerry.js +0 -5
  142. package/src/helpers/isCanvasSupported.js +0 -6
  143. package/src/helpers/isIE.js +0 -21
  144. package/src/helpers/isMobile.js +0 -10
  145. package/src/helpers/isWindows.js +0 -5
  146. package/src/helpers/isWindowsPhone.js +0 -5
  147. package/src/helpers/isiOS.js +0 -5
  148. package/src/html5media.js +0 -19
  149. package/src/index.js +0 -2
  150. package/src/logger.js +0 -31
  151. package/src/microevent.js +0 -65
  152. package/src/normalize-options.js +0 -139
  153. package/src/player.js +0 -864
  154. package/src/players/base.js +0 -209
  155. package/src/players/flash.js +0 -172
  156. package/src/players/hls.js +0 -278
  157. package/src/players/html.js +0 -205
  158. package/src/players/index.js +0 -59
  159. package/src/players/shaka.js +0 -219
  160. package/src/playlist.js +0 -362
  161. package/src/screenfull.js +0 -121
  162. package/src/state.js +0 -474
  163. package/src/static/es5.js +0 -344
  164. package/src/static/images/Spinner-small.gif +0 -0
  165. package/src/static/images/close.png +0 -0
  166. package/src/static/images/ic_check_box_black_24dp_1x.png +0 -0
  167. package/src/static/images/ic_check_box_outline_blank_black_24dp_1x.png +0 -0
  168. package/src/static/images/ic_chevron_left_white_24dp_1x.png +0 -0
  169. package/src/static/images/ic_chevron_right_white_24dp_1x.png +0 -0
  170. package/src/static/images/ic_closed_caption_white_24dp_1x.png +0 -0
  171. package/src/static/images/ic_fast_forward_white_24dp_1x.png +0 -0
  172. package/src/static/images/ic_fast_rewind_white_24dp_1x.png +0 -0
  173. package/src/static/images/ic_fullscreen_exit_white_24dp_1x.png +0 -0
  174. package/src/static/images/ic_fullscreen_white_24dp_1x.png +0 -0
  175. package/src/static/images/ic_hd_white_24dp_1x.png +0 -0
  176. package/src/static/images/ic_keyboard_arrow_left_black_24dp_1x.png +0 -0
  177. package/src/static/images/ic_keyboard_arrow_right_black_24dp_1x.png +0 -0
  178. package/src/static/images/ic_pause_white_24dp_1x.png +0 -0
  179. package/src/static/images/ic_play_arrow_white_24dp_1x.png +0 -0
  180. package/src/static/images/ic_refresh_white_24dp_1x.png +0 -0
  181. package/src/static/images/ic_settings_white_24dp_1x.png +0 -0
  182. package/src/static/images/ic_skip_next_white_24dp_1x.png +0 -0
  183. package/src/static/images/ic_skip_previous_white_24dp_1x.png +0 -0
  184. package/src/static/images/ic_toc_white_24dp_1x.png +0 -0
  185. package/src/static/images/ic_volume_off_white_24dp_1x.png +0 -0
  186. package/src/static/images/ic_volume_up_white_24dp_1x.png +0 -0
  187. package/src/static/player4ie8.css +0 -225
  188. package/src/styles/bplaylist.css.js +0 -124
  189. package/src/styles/index.js +0 -1966
  190. package/src/styles/playlist.css.js +0 -84
  191. package/src/styles/rplaylist.css.js +0 -98
  192. package/src/svgs.js +0 -111
  193. package/src/types/Logger.js +0 -10
  194. package/src/types/Options.js +0 -179
  195. package/src/types/Playlist.js +0 -3
  196. package/src/types/Source.js +0 -28
  197. package/src/types/State.js +0 -46
  198. package/src/types/Styles.js +0 -11
  199. package/src/types/TimeData.js +0 -8
  200. package/src/types/Translation.js +0 -69
  201. package/src/utils/absolutizeUrl.js +0 -9
  202. package/src/utils/addClass.js +0 -9
  203. package/src/utils/addEvent.js +0 -31
  204. package/src/utils/addProperty.js +0 -65
  205. package/src/utils/appendChild.js +0 -14
  206. package/src/utils/buff2hex.js +0 -5
  207. package/src/utils/contains.js +0 -33
  208. package/src/utils/createElement.js +0 -24
  209. package/src/utils/each.js +0 -34
  210. package/src/utils/escapeHTML.js +0 -8
  211. package/src/utils/existy.js +0 -4
  212. package/src/utils/extend.js +0 -17
  213. package/src/utils/filter.js +0 -16
  214. package/src/utils/find.js +0 -11
  215. package/src/utils/findIndex.js +0 -20
  216. package/src/utils/first.js +0 -5
  217. package/src/utils/get.js +0 -19
  218. package/src/utils/has.js +0 -5
  219. package/src/utils/hasClass.js +0 -6
  220. package/src/utils/head.js +0 -11
  221. package/src/utils/inRange.js +0 -16
  222. package/src/utils/index.js +0 -73
  223. package/src/utils/isArray.js +0 -4
  224. package/src/utils/isBoolean.js +0 -3
  225. package/src/utils/isElement.js +0 -7
  226. package/src/utils/isEmpty.js +0 -6
  227. package/src/utils/isEqual.js +0 -33
  228. package/src/utils/isEqualBuffer.js +0 -13
  229. package/src/utils/isFunction.js +0 -3
  230. package/src/utils/isNotEmpty.js +0 -5
  231. package/src/utils/isObject.js +0 -5
  232. package/src/utils/isString.js +0 -9
  233. package/src/utils/last.js +0 -4
  234. package/src/utils/map.js +0 -11
  235. package/src/utils/negate.js +0 -8
  236. package/src/utils/noop.js +0 -1
  237. package/src/utils/notExisty.js +0 -5
  238. package/src/utils/reduce.js +0 -8
  239. package/src/utils/remove.js +0 -7
  240. package/src/utils/removeClass.js +0 -8
  241. package/src/utils/removeEvent.js +0 -7
  242. package/src/utils/toArray.js +0 -7
  243. package/src/utils/toggleClass.js +0 -16
  244. package/src/utils/uidGenerator.js +0 -8
  245. package/src/utils/upperFirst.js +0 -4
  246. package/tests/extensions/__snapshots__/download.spec.js.snap +0 -226
  247. package/tests/extensions/__snapshots__/fullscreen.spec.js.snap +0 -30
  248. package/tests/extensions/__snapshots__/title.spec.js.snap +0 -16
  249. package/tests/extensions/download.spec.js +0 -111
  250. package/tests/extensions/fullscreen.spec.js +0 -56
  251. package/tests/extensions/title.spec.js +0 -35
  252. package/tests/mocks/assets/BaseM.mp4 +0 -0
  253. package/tests/mocks/assets/hls.min.js +0 -5
  254. package/tests/mocks/assets/styleMock.js +0 -1
  255. package/tests/mocks/base-player-options.js +0 -47
  256. package/tests/mocks/sources.js +0 -58
  257. package/tests/mocks/timedata/cc_en.vtt +0 -171
  258. package/tests/mocks/timedata/cc_ge.vtt +0 -178
  259. package/tests/utils/wait.js +0 -1
  260. package/webpack.config.js +0 -78
@@ -1,102 +0,0 @@
1
- import BaseExtension from './base';
2
-
3
- import { createElement, removeClass, addClass } from '../utils';
4
-
5
- import createSvg, { PAUSE, PLAY, REPLAY } from '../svgs';
6
-
7
- import popover from './helpers/popover';
8
-
9
- const CN = 'rmp-ext-play';
10
- const PLAYING_CN = `${CN}--playing`;
11
- const PAUSED_CN = `${CN}--paused`;
12
- const ENDED_CN = `${CN}--ended`;
13
-
14
- export default class PlayExtension extends BaseExtension {
15
- constructor(player, state, options) {
16
- super(player, state, options, ['pause', 'play', 'ended', 'seeking']);
17
- this.logger.debug('play:extension:creating');
18
-
19
- this.render();
20
- this.addEvent(this.$el, 'click', this.toggle.bind(this));
21
-
22
- this.logger.debug('play:extension:created');
23
- }
24
-
25
- render() {
26
- /** @type {HTMLMediaElement} */
27
- this.$el = createElement('button', { type: 'button', class: `${CN} ${PAUSED_CN}` });
28
-
29
- setTimeout(() => {
30
- const text = () => {
31
- if (this.player.isEnded()) {
32
- return this.$t('replay');
33
- } else if (this.player.isPaused()) {
34
- return this.$t('play');
35
- }
36
- return this.$t('pause');
37
- };
38
- popover(this, { $button: this.$el, text });
39
- });
40
-
41
- createSvg(this.$el, PLAY, {class: 'play'});
42
- createSvg(this.$el, PAUSE, {class: 'pause'});
43
- createSvg(this.$el, REPLAY, {class: 'replay'});
44
- }
45
-
46
- toggle() {
47
- if (this.player.isPaused() || this.player.isEnded()) {
48
- this.player.play();
49
- } else {
50
- this.player.pause();
51
- }
52
- }
53
-
54
- onPause() {
55
- this.$el.setAttribute('aria-label', 'Play');
56
- removeClass(this.$el, PLAYING_CN);
57
- removeClass(this.$el, ENDED_CN);
58
- addClass(this.$el, PAUSED_CN);
59
- }
60
-
61
- onPlay() {
62
- this.$el.setAttribute('aria-label', 'Pause');
63
- removeClass(this.$el, PAUSED_CN);
64
- removeClass(this.$el, ENDED_CN);
65
- addClass(this.$el, PLAYING_CN);
66
- }
67
-
68
- onEnded() {
69
- if (this.options.playLoop) {
70
- this.player.play();
71
- } else {
72
- this.$el.setAttribute('aria-label', 'Reply');
73
- removeClass(this.$el, PAUSED_CN);
74
- removeClass(this.$el, PLAYING_CN);
75
- addClass(this.$el, ENDED_CN);
76
- }
77
- }
78
-
79
- onSeeking() {
80
- removeClass(this.$el, ENDED_CN);
81
- removeClass(this.$el, PAUSED_CN);
82
- removeClass(this.$el, PLAYING_CN);
83
-
84
- if (this.player.isPaused()) {
85
- addClass(this.$el, PAUSED_CN);
86
- } else {
87
- addClass(this.$el, PLAYING_CN);
88
- }
89
- }
90
-
91
- getElement() {
92
- return this.$el;
93
- }
94
-
95
- destroy() {
96
- super.destroy();
97
-
98
- const parent = this.$el.parentNode;
99
- parent.removeChild(this.$el);
100
- this.$el = null;
101
- }
102
- }
@@ -1,47 +0,0 @@
1
- import BaseExtension from './base';
2
-
3
- import { createElement, addClass } from '../utils';
4
-
5
- const CN = 'rmp-ext-poster';
6
- const VIDEO_CN = `${CN}--video`;
7
- const HIDDEN_CN = `${CN}--hidden`;
8
-
9
- export default class PosterExtension extends BaseExtension {
10
- constructor(player, state, options) {
11
- super(player, state, options);
12
- this.logger.debug('poster:extension:creating');
13
-
14
- this._hidePoster = this._hidePoster.bind(this);
15
- this.render();
16
-
17
- this.logger.debug('poster:extension:created');
18
- }
19
-
20
- render() {
21
- this.$outer = createElement('div', { class: CN, tabindex: -1 });
22
- const img = createElement('img', { src: this.options.poster }, this.$outer);
23
- img.setAttribute('aria-label', this.options.title);
24
- if (!this.options.isAudio) {
25
- addClass(this.$outer, VIDEO_CN);
26
- this.bus.on('play', this._hidePoster);
27
- }
28
- }
29
-
30
- _hidePoster() {
31
- addClass(this.$outer, HIDDEN_CN);
32
- }
33
-
34
- getOuter() {
35
- return this.$outer;
36
- }
37
-
38
- destroy() {
39
- this.bus.off('play', this._hidePoster);
40
- super.destroy();
41
- if (this.$outer) {
42
- const parent = this.$outer.parentNode;
43
- parent.removeChild(this.$outer);
44
- this.$outer = null;
45
- }
46
- }
47
- }
@@ -1,44 +0,0 @@
1
- import BaseExtension from './base';
2
-
3
- import createElement from '../utils/createElement';
4
-
5
- import popover from './helpers/popover';
6
-
7
- import createSvg, { PREV_TRACK } from '../svgs';
8
-
9
- const CN = 'rmp-ext-prev-frame';
10
-
11
- export default class PrevFrameExtension extends BaseExtension {
12
- constructor(player, state, options) {
13
- super(player, state, options);
14
- this.logger.debug('prevframe:extension:creating');
15
-
16
- this.render();
17
- this.addEvent(this.$el, 'click', this.prevframe.bind(this));
18
-
19
- this.logger.debug('prevframe:extension:created');
20
- }
21
-
22
- render() {
23
- /** @type {HTMLMediaElement} */
24
- this.$el = createElement('button', { type: 'button', class: CN });
25
- setTimeout(() => popover(this, { $button: this.$el, text: this.$t('prevframe') }) );
26
- createSvg(this.$el, PREV_TRACK);
27
- }
28
-
29
- prevframe() {
30
- this.player.prevFrame();
31
- }
32
-
33
- getElement() {
34
- return this.$el;
35
- }
36
-
37
- destroy() {
38
- super.destroy();
39
-
40
- const parent = this.$el.parentNode;
41
- parent.removeChild(this.$el);
42
- this.$el = null;
43
- }
44
- }
@@ -1,48 +0,0 @@
1
- import BaseExtension from './base';
2
-
3
- import createElement from '../utils/createElement';
4
- import createSvg, { PREV_TRACK } from '../svgs';
5
-
6
- const CN = 'rmp-ext-prev';
7
- const BUTTON_CN = `${CN}__button`;
8
- const THUMBNAIL_CN = `${CN}__thumbnail`;
9
-
10
- export default class PrevExtension extends BaseExtension {
11
- /** @type {HTMLElement} */
12
- $outer;
13
- /** @type {HTMLButtonElement} */
14
- $button;
15
-
16
- constructor(player, state, options) {
17
- super(player, state, options);
18
- this.logger.debug('prev:extension:creating');
19
-
20
- this.render();
21
-
22
- const bus = this.options.bus;
23
-
24
- this.addEvent(this.$outer, 'click', () => bus.emit('prevtrack') );
25
-
26
- this.logger.debug('prev:extension:created');
27
- }
28
-
29
- render() {
30
- const title = this.options.prevTrackTitle;
31
- this.$outer = createElement('div', { class: CN, title });
32
- this.$button = createElement('button', { type: 'button', class: BUTTON_CN }, this.$outer);
33
- createSvg(this.$button, PREV_TRACK);
34
- this.$button.setAttribute('aria-label', 'Go to previous track');
35
-
36
- createElement('img', { src: this.options.prevTrackThumbnails, class: THUMBNAIL_CN }, this.$outer);
37
- }
38
-
39
- getOuter() {
40
- return this.$outer;
41
- }
42
-
43
- destroy() {
44
- super.destroy();
45
- this.$outer.parentNode.removeChild(this.$outer);
46
- this.$outer = null;
47
- }
48
- }
@@ -1,465 +0,0 @@
1
- import BaseExtension from './base';
2
-
3
- import {
4
- existy, createElement, last, find, inRange, isEmpty, each, removeEvent, addEvent, isNotEmpty, hasClass
5
- } from '../utils';
6
-
7
- import loadVTT from './helpers/vtt-loader';
8
- import popoverPosition from './helpers/popoverPosition';
9
-
10
- import type { Player$State } from '../types/State';
11
- import addClass from '../utils/addClass';
12
-
13
- const CN = 'rmp-ext-progress';
14
- const CURRENT_TIME_CN = `${CN}__current`;
15
- const DURATION_TIME_CN = `${CN}__duration`;
16
- const BAR_CN = `${CN}__bar`;
17
- const BAR_PADDING_CN = `${CN}__bar-padding`;
18
- const HANDLE_CN = `${CN}__handle`;
19
- const OVERALY_CN = `${CN}__overlay`;
20
- const PLAY_PROGRESS_CN = `${CN}__play-progress`;
21
- const PROGRESS_CN = `${CN}__progress`;
22
- const C2PA_STATUS_CN = `${CN}__c2pa-status`;
23
- const C2PA_STATUS_INVALID_SEGMENT_CN = `${C2PA_STATUS_CN}--invalid-segment`;
24
-
25
- const TOOLTIP_CN = `${CN}__tooltip`;
26
- const TOOLTIP_VISIBLE_CN = `${CN}__tooltip--visible`;
27
- const THUMBNAIL_CN = `${CN}__thumbmail`;
28
- const THUMBNAIL_TIME_CN = `${CN}__thumbmail-time`;
29
- const DISABLE_SLIDE_CN = `${CN}__generic-live-stream`;
30
- const HIDDEN_CN = `${CN}__hidden`;
31
-
32
- const CHAPTER_BUBBLE_CN = `${CN}__chapter-bubble`;
33
-
34
- const SECS_IN_HOUR = 3600; // 60 * 60
35
- const SECS_IN_MIN = 60;
36
-
37
- const TEN = 10;
38
-
39
- export default class ProgressExtension extends BaseExtension {
40
- thumbnails = [];
41
- _dragNdropTokens = [];
42
- _isLoadedMetadata = false;
43
- _chapters = [];
44
- _bubbles = [];
45
-
46
- constructor(player, state, options) {
47
- super(player, state, options, [
48
- 'progress', 'timeupdate', 'loadedmetadata', 'canplaythrough', 'statechanged', 'c2pafragment', 'durationchange'
49
- ]);
50
- this.logger.debug('progress:extension:creating');
51
-
52
- this.onLeave = this.onLeave.bind(this);
53
- this.onHover = this.onHover.bind(this);
54
- this.onHandleMouseUp = this.onHandleMouseUp.bind(this);
55
- this.onHandleMouseDown = this.onHandleMouseDown.bind(this);
56
- this.onHandleMouseMove = this.onHandleMouseMove.bind(this);
57
- this.onTouchStart = this.onTouchStart.bind(this);
58
- this.onTouchMove = this.onTouchMove.bind(this);
59
- this.onTouchEnd = this.onTouchEnd.bind(this);
60
-
61
- this.render();
62
-
63
- this.addEvent(this.$bar, 'click', e => {
64
- const target = e.target || e.srcElement;
65
- if (target === this.$handle) {
66
- e.stopPropagation();
67
- } else {
68
- const time = this._getTimeByEventPosition(e);
69
- player.setCurrentTime(time);
70
- this._moveHandle2time(time);
71
- }
72
- });
73
-
74
- this.addEvent(this.$bar, 'mouseleave', this.onLeave);
75
- this.addEvent(this.$bar, 'mousemove', this.onHover);
76
- this.addEvent(this.$handle, 'mousedown', this.onHandleMouseDown);
77
- this.addEvent(this.$handle, 'touchstart', this.onTouchStart);
78
-
79
- if (existy(options.preview)) {
80
- loadVTT(options.preview, resp => this.thumbnails = resp);
81
- }
82
-
83
- this.logger.debug('progress:extension:created');
84
- }
85
-
86
- render() {
87
- /** @type {HTMLMediaElement} */
88
- this.$el = createElement('span', { class: CN });
89
-
90
- /** @type {HTMLMediaElement} */
91
- const extensions = this.player.$el.parentNode.querySelector('.rmp-extensions');
92
-
93
- this.$bar = createElement('span', { class: BAR_CN, tabindex: 0 }, extensions);
94
- createElement('span', { class: BAR_PADDING_CN }, this.$bar);
95
- createElement('span', { class: OVERALY_CN }, this.$bar);
96
-
97
- /** @type {HTMLMediaElement} */
98
- this.$handle = createElement('span', { class: HANDLE_CN }, this.$bar);
99
- /** @type {HTMLMediaElement} */
100
- this.$current = createElement('span', { class: CURRENT_TIME_CN }, this.$el);
101
- /** @type {HTMLMediaElement} */
102
- const span = createElement('span', { }, this.$el);
103
- span.textContent = '/';
104
- this.$duration = createElement('span', { class: DURATION_TIME_CN }, this.$el);
105
- this.$c2paStatus = createElement('span', { class: C2PA_STATUS_CN }, this.$bar);
106
- this.$playProgress = createElement('span', { class: PLAY_PROGRESS_CN }, this.$bar);
107
- this.$progress = createElement('span', { class: PROGRESS_CN }, this.$bar);
108
-
109
- this.$tooltip = createElement('div', { class: TOOLTIP_CN }, this.$el);
110
- this.$thumbnail = createElement('div', { class: THUMBNAIL_CN }, this.$tooltip);
111
- this.$thumbnailTime = createElement('span', { class: THUMBNAIL_TIME_CN }, this.$tooltip);
112
-
113
- if (this.options.isProgressLiveStream) {
114
- addClass(this.$el, DISABLE_SLIDE_CN);
115
- addClass(this.$bar, DISABLE_SLIDE_CN);
116
- }
117
-
118
- if (this.options.isLive) {
119
- addClass(this.$el, HIDDEN_CN);
120
- }
121
-
122
- if ( this.options.isMobile ) {
123
- this.$tooltip.style.visibility = 'hidden';
124
- }
125
- }
126
-
127
- onTimeupdate() {
128
- if ( isNotEmpty(this._dragNdropTokens) ) {
129
- return;
130
- }
131
-
132
- if (this.options.isLive && this.player?.isLive()) {
133
- this.$progress.style.width = '100%';
134
- this.$handle.style.left = this.$playProgress.style.width = '100%';
135
- this.$current.textContent = secondsToTimeCode(+this._getCurrentTime());
136
- // Accessibility: Set correct values for screen readers
137
- this.$bar.setAttribute('aria-label', this._getAriaLabelValue());
138
- } else {
139
- this._moveHandle2time(this._getCurrentTime());
140
- }
141
- }
142
-
143
- _moveHandle2time(time) {
144
- const duration = this.player.getDuration();
145
- const { timecode, clip } = this.options;
146
- if (existy(time) && duration) {
147
- this.$current.textContent = secondsToTimeCode(+time);
148
- // Accessibility: Set correct values for screen readers
149
- this.$bar.setAttribute('aria-label', this._getAriaLabelValue());
150
- let percent;
151
-
152
- if ( clip ) {
153
- let [ start, end ] = clip;
154
- start = start || 0;
155
- end = end ? end + timecode : duration + start;
156
- percent = (time - start - timecode) / (end - start - timecode);
157
- } else {
158
- percent = (time - timecode) / (duration - timecode);
159
- }
160
-
161
- const position = (100 * percent).toFixed(2) + '%';
162
- this.$handle.style.left = this.$playProgress.style.width = position;
163
- }
164
- }
165
-
166
- onProgress() {
167
- this.$duration.textContent = secondsToTimeCode(this._getDuration()); // for live streams
168
- this.$progress.style.width = 100 * this.player.getBufferedPercent() + '%';
169
- }
170
-
171
- onHandleMouseDown() {
172
- this._dragNdropTokens.push( addEvent(document, 'mouseup', this.onHandleMouseUp) );
173
- this._dragNdropTokens.push( addEvent(document, 'mousemove', this.onHandleMouseMove) );
174
- }
175
-
176
- onTouchStart() {
177
- this._dragNdropTokens.push( addEvent(document, 'touchend', this.onTouchEnd) );
178
- this._dragNdropTokens.push( addEvent(document, 'touchmove', this.onTouchMove) );
179
- }
180
-
181
- onHandleMouseUp(e) {
182
- e.stopPropagation();
183
- e.preventDefault();
184
- each(this._dragNdropTokens, removeEvent);
185
- this._dragNdropTokens.length = 0;
186
- this.player.setCurrentTime(this._getTimeByEventPosition(e));
187
- }
188
-
189
- onTouchMove(e) {
190
- e.stopPropagation();
191
- e.preventDefault();
192
- const rect = this.$bar.getBoundingClientRect();
193
- const touch = e.touches[0];
194
- let left = Math.max(rect.left, touch.clientX);
195
- left = Math.min(rect.right, left);
196
- left -= rect.left;
197
- left = 100 * (left / this.$bar.offsetWidth) + '%';
198
- this.$handle.style.left = this.$playProgress.style.width = left;
199
- const time = this._getTimeByEventPosition(touch);
200
- this.player.setCurrentTime(time);
201
- this.bus.emit('heartbeatextensions');
202
- }
203
-
204
- onTouchEnd(e) {
205
- e.stopPropagation();
206
- e.preventDefault();
207
- each(this._dragNdropTokens, removeEvent);
208
- this._dragNdropTokens.length = 0;
209
- }
210
-
211
- onHandleMouseMove(e) {
212
- const rect = this.$bar.getBoundingClientRect();
213
- // const parentRect = this.player.getElement().parentNode.getBoundingClientRect();
214
- let left = Math.max(rect.left, e.clientX);
215
- left = Math.min(rect.right, left);
216
- left -= rect.left;
217
- left = 100 * (left / this.$bar.offsetWidth) + '%';
218
- this.$handle.style.left = this.$playProgress.style.width = left;
219
- }
220
-
221
- onDurationchange() {
222
- if (!this.options.isLive && !this.isProgressLiveStream) {
223
- this._updateTimes();
224
- }
225
- }
226
-
227
- onCanplaythrough() {
228
- this._updateTimes();
229
- }
230
-
231
- onLoadedmetadata() {
232
- this._updateTimes();
233
- }
234
-
235
- onC2pafragment(fragment) {
236
- if (fragment.valid) return;
237
-
238
- setTimeout(() => {
239
- const duration = this.player.getDuration();
240
- const start = fragment.start;
241
- const fragDuration = fragment.duration;
242
- const startPercent = (start / duration) * 100;
243
- const widthPercent = (fragDuration / duration) * 100;
244
-
245
- const $fragment = createElement('span', { class: C2PA_STATUS_INVALID_SEGMENT_CN }, this.$c2paStatus);
246
-
247
- $fragment.style.left = startPercent + '%';
248
- $fragment.style.width = widthPercent + '%';
249
- }, 1000);
250
- }
251
-
252
- // Accessibility: Screen reader expect hours to be present in the timecode
253
- _getAriaLabelValue() {
254
- const current = this.$current.textContent;
255
- const duration = this.$duration.textContent;
256
-
257
- return `Current: ${this._timeCodeToSentence(current)} Total: ${this._timeCodeToSentence(duration)}`;
258
- }
259
-
260
- // Accessibility
261
- _timeCodeToSentence(time) {
262
- const parts = time.split(':');
263
- const words = ['minutes', 'seconds'];
264
-
265
- if (parts.length > 2) words.unshift('hours');
266
-
267
- const formatted = parts.map((p, idx) => {
268
- const value = p.charAt(0) === '0' ? p.charAt(1) : p;
269
- return `${value} ${words[idx]}`;
270
- });
271
-
272
- return formatted.join(' ');
273
- }
274
-
275
- _getDuration() {
276
- const { clip, timecode } = this.options;
277
- const duration = this.player.getDuration();
278
-
279
- if ( clip ) {
280
- let [ start, end ] = clip; // eslint-disable-line no-unused-vars
281
- start = start || 0;
282
- return end ? end + timecode : duration + start;
283
- }
284
-
285
- return duration;
286
- }
287
-
288
- _getCurrentTime() {
289
- const time = this.player.getCurrentTime();
290
- const { clip, timecode } = this.options;
291
- const [ start ] = clip || [ 0 ];
292
- return Math.max(time, start + timecode);
293
- }
294
-
295
- onLeave() {
296
- this.$tooltip.classList.remove(TOOLTIP_VISIBLE_CN);
297
- }
298
-
299
- onHover(e) {
300
- let time;
301
- const { useOriginTimeForPreview, timecode } = this.options;
302
- const target = e.target || e.srcElement;
303
- if ( hasClass(target, CHAPTER_BUBBLE_CN) ) {
304
- const idx = parseInt(target.getAttribute('data-idx'), 10);
305
- const chapter = this._chapters[idx];
306
- time = chapter.from;
307
- this.$thumbnailTime.innerHTML = chapter.text || chapter.title;
308
- } else {
309
- time = this._getTimeByEventPosition(e);
310
- this.$thumbnailTime.textContent = secondsToTimeCode(time);
311
- }
312
-
313
- if (isEmpty(this.thumbnails)) {
314
- this._popoverPosition(e);
315
- return;
316
- }
317
-
318
- const tt = useOriginTimeForPreview ? time - timecode : time;
319
- const thumbnail = find(this.thumbnails, ({ from, to }) => inRange(tt, from, to));
320
- if (thumbnail) {
321
- const [url, hash] = thumbnail.text.split('#');
322
-
323
- this.$thumbnail.style.backgroundImage = `url("${url}")`;
324
-
325
- const xywh = last(hash.split('=')).split(',');
326
- const h = xywh.pop().trim();
327
- const w = xywh.pop().trim();
328
- const y = xywh.pop().trim();
329
- const x = xywh.pop().trim();
330
-
331
- this.$thumbnail.style.width = `${w}px`;
332
- this.$thumbnail.style.height = `${h}px`;
333
- this.$thumbnail.style.backgroundPosition = `-${x}px -${y}px`;
334
- this.$thumbnail.style.marginBottom = '7px';
335
- } else {
336
- this.$thumbnail.style.height = '';
337
- this.$thumbnail.style.width = '';
338
- this.$thumbnail.style.marginBottom = '';
339
- }
340
- this._popoverPosition(e);
341
- }
342
-
343
- _updateTimes() {
344
- this.$duration.textContent = secondsToTimeCode(this._getDuration());
345
- this.$current.textContent = secondsToTimeCode(this._getCurrentTime());
346
- // Accessibility: Set correct values for screen readers
347
- this.$bar.setAttribute('aria-label', this._getAriaLabelValue());
348
- this._isLoadedMetadata = true;
349
- this._renderChaptersIfNeeded();
350
- }
351
-
352
- _popoverPosition(e) {
353
- popoverPosition(this.player, this._offsetX(e), this.$tooltip);
354
- this.$tooltip.classList.add(TOOLTIP_VISIBLE_CN);
355
- }
356
-
357
- onStatechanged(state: Player$State, old: Player$State) {
358
- if (state.toc.lang !== old.toc.lang) {
359
- this._refreshTOC();
360
- } else if ( state.toc.timedata !== old.toc.timedata ) {
361
- this._refreshTOC();
362
- }
363
- }
364
-
365
- _refreshTOC() {
366
- const chapters = this.state.getTOCTimeData();
367
- const lang = this.state.getTOCLang();
368
- this._chapters = lang ? chapters : [];
369
- this._renderChaptersIfNeeded();
370
- }
371
-
372
- _renderChaptersIfNeeded() {
373
- each(this._bubbles, b => this.$bar.removeChild(b));
374
- this._bubbles.length = 0;
375
- if ( isEmpty(this._chapters) || !this._isLoadedMetadata ) {
376
- return;
377
- }
378
-
379
- const duration = this.player.getDuration();
380
-
381
- each(this._chapters, (c, idx) => {
382
- const bubble = createElement('span', { class: CHAPTER_BUBBLE_CN, 'data-idx': idx }, this.$bar );
383
- bubble.style.left = (100 * c.from / duration).toFixed(0) + '%';
384
- this.addEvent(bubble, 'click', e => {
385
- e.stopPropagation();
386
- this._moveHandle2time(c.from);
387
- this.player.setCurrentTime(c.from);
388
- });
389
- this._bubbles.push(bubble);
390
- });
391
- }
392
-
393
- _getTimeByEventPosition(e) {
394
- const duration = this.player.getDuration();
395
- const { timecode, clip } = this.options;
396
- const percent = this._getPercentageByPosition(e);
397
-
398
- if (clip) {
399
- let [ start, end ] = clip;
400
- start = start || 0;
401
- end = end || duration + start - timecode;
402
- return ((end - start) * percent + start + timecode).toFixed(2);
403
- }
404
-
405
- return parseFloat(((duration - timecode) * percent + timecode).toFixed(2));
406
- }
407
-
408
- _getPercentageByPosition(e) {
409
- const rect = this.$bar.getBoundingClientRect();
410
- let left = Math.max(rect.left, e.clientX);
411
- left = Math.min(rect.right, left);
412
- left -= rect.left;
413
- return (left / this.$bar.offsetWidth).toFixed(2);
414
- }
415
-
416
- _offsetX(e) {
417
- if (!this.player.getElement()) return;
418
-
419
- const rect = this.$bar.getBoundingClientRect();
420
- const parentRect = this.player.getElement().parentNode.getBoundingClientRect();
421
- let left = Math.max(rect.left, e.clientX);
422
- left = Math.min(rect.right, left);
423
- left -= parentRect.left;
424
- return left;
425
- }
426
-
427
- getElement() {
428
- return this.$el;
429
- }
430
-
431
- destroy() {
432
- super.destroy();
433
-
434
- const parent = this.$el.parentNode;
435
-
436
- parent.removeChild(this.$el);
437
-
438
- this.$el = null;
439
- this.$bar = null;
440
- this.$handle = null;
441
- this.$current = null;
442
- this.$duration = null;
443
- this.$playProgress = null;
444
- this.$progress = null;
445
- this.$tooltip = null;
446
- this.$thumbnail = null;
447
- this.$thumbnailTime = null;
448
- }
449
- }
450
-
451
- function secondsToTimeCode(time) {
452
- if (time === Infinity || isNaN(time)) {
453
- return '--:--';
454
- }
455
-
456
- const hours = Math.floor(time / SECS_IN_HOUR);
457
- const minutes = Math.floor(time / SECS_IN_MIN) % SECS_IN_MIN;
458
- const seconds = Math.floor(time % SECS_IN_MIN);
459
-
460
- return (hours ? _pad(hours) + ':' : '') + _pad(minutes) + ':' + _pad(seconds);
461
- }
462
-
463
- function _pad(num) {
464
- return num < TEN ? `0${num}` : `${num}`;
465
- }