@gcorevideo/player 2.28.24 → 2.28.26

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 (147) hide show
  1. package/dist/core.js +45 -32
  2. package/dist/index.css +305 -305
  3. package/dist/index.embed.js +119 -40
  4. package/dist/index.js +255 -124
  5. package/lib/Player.d.ts.map +1 -1
  6. package/lib/index.core.d.ts +1 -1
  7. package/lib/index.core.d.ts.map +1 -1
  8. package/lib/index.core.js +1 -1
  9. package/lib/index.plugins.d.ts +34 -34
  10. package/lib/index.plugins.d.ts.map +1 -1
  11. package/lib/index.plugins.js +34 -34
  12. package/lib/playback/dash-playback/DashPlayback.d.ts +4 -0
  13. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  14. package/lib/playback/dash-playback/DashPlayback.js +7 -0
  15. package/lib/playback/types.d.ts.map +1 -1
  16. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  17. package/lib/plugins/bottom-gear/BottomGear.js +3 -1
  18. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -1
  19. package/lib/plugins/clappr-nerd-stats/speedtest/index.js +9 -5
  20. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts.map +1 -1
  21. package/lib/plugins/clappr-nerd-stats/utils.d.ts +2 -2
  22. package/lib/plugins/clips/utils.d.ts.map +1 -1
  23. package/lib/plugins/cmcd-config/CmcdConfig.js +1 -1
  24. package/lib/plugins/favicon/Favicon.d.ts.map +1 -1
  25. package/lib/plugins/google-analytics/GoogleAnalytics.d.ts.map +1 -1
  26. package/lib/plugins/google-analytics/GoogleAnalytics.js +10 -3
  27. package/lib/plugins/kibo/index.d.ts.map +1 -1
  28. package/lib/plugins/kibo/index.js +69 -20
  29. package/lib/plugins/level-selector/QualityLevels.js +2 -2
  30. package/lib/plugins/logo/Logo.d.ts.map +1 -1
  31. package/lib/plugins/logo/Logo.js +19 -15
  32. package/lib/plugins/logo/utils/index.d.ts.map +1 -1
  33. package/lib/plugins/logo/utils/index.js +11 -7
  34. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  35. package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -1
  36. package/lib/plugins/multi-camera/MultiCamera.js +42 -20
  37. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  38. package/lib/plugins/picture-in-picture/PictureInPicture.js +3 -2
  39. package/lib/plugins/share/Share.d.ts.map +1 -1
  40. package/lib/plugins/share/Share.js +17 -12
  41. package/lib/plugins/skip-time/SkipTime.d.ts.map +1 -1
  42. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  43. package/lib/plugins/subtitles/ClosedCaptions.d.ts +2 -0
  44. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  45. package/lib/plugins/subtitles/ClosedCaptions.js +25 -5
  46. package/lib/plugins/thumbnails/Thumbnails.js +2 -3
  47. package/lib/plugins/thumbnails/utils.d.ts.map +1 -1
  48. package/lib/plugins/utils/fullscreen.d.ts.map +1 -1
  49. package/lib/plugins/utils.d.ts.map +1 -1
  50. package/lib/plugins/utils.js +1 -1
  51. package/lib/plugins/vast-ads/VastAds.d.ts.map +1 -1
  52. package/lib/plugins/vast-ads/VastAds.js +2 -1
  53. package/lib/plugins/vast-ads/loaderxml.d.ts.map +1 -1
  54. package/lib/plugins/vast-ads/loaderxml.js +8 -5
  55. package/lib/plugins/vast-ads/roll.d.ts +2 -2
  56. package/lib/plugins/vast-ads/roll.d.ts.map +1 -1
  57. package/lib/plugins/vast-ads/roll.js +16 -10
  58. package/lib/plugins/vast-ads/rollmanager.d.ts.map +1 -1
  59. package/lib/plugins/vast-ads/rollmanager.js +17 -7
  60. package/lib/plugins/vast-ads/sctemanager.d.ts +1 -1
  61. package/lib/plugins/vast-ads/sctemanager.d.ts.map +1 -1
  62. package/lib/plugins/vast-ads/sctemanager.js +6 -5
  63. package/lib/plugins/vast-ads/types.d.ts.map +1 -1
  64. package/lib/plugins/vast-ads/urlhandler.d.ts.map +1 -1
  65. package/lib/plugins/vast-ads/xmlhttprequest.d.ts.map +1 -1
  66. package/lib/plugins/vast-ads/xmlhttprequest.js +3 -2
  67. package/lib/plugins/vast-ads/xmlmerge.d.ts.map +1 -1
  68. package/lib/plugins/vast-ads/xmlmerge.js +4 -3
  69. package/lib/types.d.ts +1 -1
  70. package/lib/types.d.ts.map +1 -1
  71. package/lib/utils/clickaway.d.ts.map +1 -1
  72. package/lib/utils/mediaSources.d.ts.map +1 -1
  73. package/lib/utils/mediaSources.js +1 -3
  74. package/lib/utils/types.d.ts.map +1 -1
  75. package/lib/version.js +2 -2
  76. package/package.json +2 -2
  77. package/src/Player.ts +10 -10
  78. package/src/__tests__/Player.test.ts +33 -10
  79. package/src/index.core.ts +9 -1
  80. package/src/index.plugins.ts +35 -35
  81. package/src/playback/__tests__/HTML5Video.test.ts +10 -4
  82. package/src/playback/dash-playback/DashPlayback.ts +8 -0
  83. package/src/playback/dash-playback/__tests__/DashPlayback.test.ts +10 -38
  84. package/src/playback/hls-playback/__tests__/HlsPlayback.test.ts +12 -45
  85. package/src/playback/types.ts +0 -1
  86. package/src/playback.types.ts +1 -2
  87. package/src/plugins/audio-selector/AudioTracks.ts +1 -1
  88. package/src/plugins/audio-selector/__tests__/AudioTracks.test.ts +30 -11
  89. package/src/plugins/bottom-gear/BottomGear.ts +3 -2
  90. package/src/plugins/clappr-nerd-stats/NerdStats.ts +1 -1
  91. package/src/plugins/clappr-nerd-stats/speedtest/index.ts +104 -82
  92. package/src/plugins/clappr-nerd-stats/speedtest/types.ts +3 -3
  93. package/src/plugins/clappr-nerd-stats/utils.ts +2 -2
  94. package/src/plugins/clappr-stats/__tests__/ClapprStats.test.ts +30 -18
  95. package/src/plugins/clips/utils.ts +5 -1
  96. package/src/plugins/cmcd-config/CmcdConfig.ts +1 -1
  97. package/src/plugins/error-screen/__tests__/ErrorScreen.test.ts +21 -15
  98. package/src/plugins/favicon/Favicon.ts +73 -49
  99. package/src/plugins/google-analytics/GoogleAnalytics.ts +93 -58
  100. package/src/plugins/kibo/index.ts +183 -109
  101. package/src/plugins/level-selector/QualityLevels.ts +2 -2
  102. package/src/plugins/logo/Logo.ts +134 -105
  103. package/src/plugins/logo/utils/index.ts +27 -20
  104. package/src/plugins/media-control/MediaControl.ts +12 -6
  105. package/src/plugins/multi-camera/MultiCamera.ts +218 -157
  106. package/src/plugins/picture-in-picture/PictureInPicture.ts +41 -37
  107. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +25 -11
  108. package/src/plugins/poster/__tests__/Poster.test.ts +8 -9
  109. package/src/plugins/share/Share.ts +85 -60
  110. package/src/plugins/skip-time/SkipTime.ts +5 -1
  111. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +8 -5
  112. package/src/plugins/subtitles/ClosedCaptions.ts +30 -6
  113. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +2 -3
  114. package/src/plugins/thumbnails/Thumbnails.ts +22 -21
  115. package/src/plugins/thumbnails/__tests__/Thumbnails.test.ts +14 -7
  116. package/src/plugins/thumbnails/utils.ts +3 -1
  117. package/src/plugins/typings/globals.d.ts +7 -7
  118. package/src/plugins/typings/workers.d.ts +3 -3
  119. package/src/plugins/utils/fullscreen.ts +2 -2
  120. package/src/plugins/utils.ts +17 -13
  121. package/src/plugins/vast-ads/VastAds.ts +4 -5
  122. package/src/plugins/vast-ads/loaderxml.ts +142 -101
  123. package/src/plugins/vast-ads/roll.ts +381 -284
  124. package/src/plugins/vast-ads/rollmanager.ts +214 -170
  125. package/src/plugins/vast-ads/sctemanager.ts +66 -48
  126. package/src/plugins/vast-ads/types.ts +15 -9
  127. package/src/plugins/vast-ads/urlhandler.ts +18 -13
  128. package/src/plugins/vast-ads/xmlhttprequest.ts +25 -20
  129. package/src/plugins/vast-ads/xmlmerge.ts +42 -32
  130. package/src/plugins/video360/VRControls.js +50 -42
  131. package/src/plugins/video360/VREffect.js +298 -206
  132. package/src/plugins/video360/Video360.js +553 -423
  133. package/src/plugins/video360/orbit-oriention-controls.js +526 -421
  134. package/src/plugins/video360/utils.js +18 -18
  135. package/src/types.ts +5 -3
  136. package/src/typings/@clappr/core/error_mixin.d.ts +9 -9
  137. package/src/typings/@clappr/core/index.d.ts +1 -3
  138. package/src/typings/@clappr/core/playback.d.ts +3 -3
  139. package/src/typings/@clappr/index.d.ts +1 -1
  140. package/src/typings/globals.d.ts +15 -15
  141. package/src/utils/__tests__/mediaSources.test.ts +42 -26
  142. package/src/utils/clickaway.ts +24 -24
  143. package/src/utils/errors.ts +2 -2
  144. package/src/utils/mediaSources.ts +5 -4
  145. package/src/utils/types.ts +1 -1
  146. package/src/version.ts +2 -2
  147. package/tsconfig.tsbuildinfo +1 -1
@@ -1,16 +1,16 @@
1
- import { UICorePlugin, template, Events } from '@clappr/core';
2
- import { trace } from '@gcorevideo/utils';
1
+ import { UICorePlugin, template, Events } from '@clappr/core'
2
+ import { trace } from '@gcorevideo/utils'
3
3
 
4
- import { CLAPPR_VERSION } from '../../build.js';
4
+ import { CLAPPR_VERSION } from '../../build.js'
5
5
 
6
- import pipIcon from '../../../assets/icons/new/pip.svg';
7
- import buttonHtml from '../../../assets/picture-in-picture/button.ejs';
8
- import '../../../assets/picture-in-picture/style.scss';
9
- import assert from 'assert';
6
+ import pipIcon from '../../../assets/icons/new/pip.svg'
7
+ import buttonHtml from '../../../assets/picture-in-picture/button.ejs'
8
+ import '../../../assets/picture-in-picture/style.scss'
9
+ import assert from 'assert'
10
10
 
11
- const VERSION = '0.0.1';
11
+ const VERSION = '0.0.1'
12
12
 
13
- const T = `plugins.pip`;
13
+ const T = `plugins.pip`
14
14
 
15
15
  /**
16
16
  * `PLUGIN` that enables picture-in-picture mode.
@@ -27,24 +27,24 @@ export class PictureInPicture extends UICorePlugin {
27
27
  * @internal
28
28
  */
29
29
  get name() {
30
- return 'pip';
30
+ return 'pip'
31
31
  }
32
32
 
33
33
  /**
34
34
  * @internal
35
35
  */
36
36
  get supportedVersion() {
37
- return { min: CLAPPR_VERSION };
37
+ return { min: CLAPPR_VERSION }
38
38
  }
39
39
 
40
40
  /**
41
41
  * @internal
42
42
  */
43
43
  static get version() {
44
- return VERSION;
44
+ return VERSION
45
45
  }
46
46
 
47
- private static buttonTemplate = template(buttonHtml);
47
+ private static buttonTemplate = template(buttonHtml)
48
48
 
49
49
  /**
50
50
  * @internal
@@ -52,17 +52,17 @@ export class PictureInPicture extends UICorePlugin {
52
52
  override get events() {
53
53
  return {
54
54
  'click button': 'togglePictureInPicture',
55
- };
55
+ }
56
56
  }
57
57
 
58
58
  override get attributes() {
59
59
  return {
60
- 'class': 'media-control-pip',
61
- };
60
+ class: 'media-control-pip',
61
+ }
62
62
  }
63
63
 
64
64
  private get videoElement() {
65
- return this.core.activePlayback.el;
65
+ return this.core.activePlayback.el
66
66
  }
67
67
 
68
68
  /**
@@ -70,19 +70,23 @@ export class PictureInPicture extends UICorePlugin {
70
70
  */
71
71
  override bindEvents() {
72
72
  this.listenToOnce(this.core, Events.CORE_READY, () => {
73
- const mediaControl = this.core.getPlugin('media_control');
74
- assert(mediaControl, 'media_control plugin is required');
75
- this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render);
76
- });
73
+ const mediaControl = this.core.getPlugin('media_control')
74
+ assert(mediaControl, 'media_control plugin is required')
75
+ this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.render)
76
+ })
77
77
  }
78
78
 
79
79
  private isPiPSupported() {
80
80
  trace(`${T} isPiPSupported`, {
81
81
  pictureInPictureEnabled: !!document.pictureInPictureEnabled,
82
- requestPictureInPicture: !!HTMLVideoElement.prototype.requestPictureInPicture,
83
- });
84
-
85
- return document.pictureInPictureEnabled && !!HTMLVideoElement.prototype.requestPictureInPicture;
82
+ requestPictureInPicture:
83
+ !!HTMLVideoElement.prototype.requestPictureInPicture,
84
+ })
85
+
86
+ return (
87
+ document.pictureInPictureEnabled &&
88
+ !!HTMLVideoElement.prototype.requestPictureInPicture
89
+ )
86
90
  }
87
91
 
88
92
  /**
@@ -90,37 +94,37 @@ export class PictureInPicture extends UICorePlugin {
90
94
  */
91
95
  override render() {
92
96
  if (!this.isPiPSupported()) {
93
- return this;
97
+ return this
94
98
  }
95
99
 
96
- this.$el.html(PictureInPicture.buttonTemplate({ pipIcon }));
100
+ this.$el.html(PictureInPicture.buttonTemplate({ pipIcon }))
97
101
 
98
- const mediaControl = this.core.getPlugin('media_control');
102
+ const mediaControl = this.core.getPlugin('media_control')
99
103
  if (mediaControl) {
100
- mediaControl.slot('pip', this.$el);
104
+ mediaControl.slot('pip', this.$el)
101
105
  }
102
106
 
103
- return this;
107
+ return this
104
108
  }
105
109
 
106
110
  private togglePictureInPicture() {
107
- trace(`${T} togglePictureInPicture`);
111
+ trace(`${T} togglePictureInPicture`)
108
112
  if (this.videoElement !== document.pictureInPictureElement) {
109
- this.requestPictureInPicture();
113
+ this.requestPictureInPicture()
110
114
  } else {
111
- this.exitPictureInPicture();
115
+ this.exitPictureInPicture()
112
116
  }
113
117
  }
114
118
 
115
119
  private requestPictureInPicture() {
116
120
  trace(`${T} requestPictureInPicture`, {
117
121
  videoElement: !!this.videoElement,
118
- });
119
- this.videoElement.requestPictureInPicture();
122
+ })
123
+ this.videoElement.requestPictureInPicture()
120
124
  }
121
125
 
122
126
  private exitPictureInPicture() {
123
- trace(`${T} exitPictureInPicture`);
124
- document.exitPictureInPicture();
127
+ trace(`${T} exitPictureInPicture`)
128
+ document.exitPictureInPicture()
125
129
  }
126
130
  }
@@ -55,7 +55,10 @@ describe('PlaybackRate', () => {
55
55
  })
56
56
  describe('until media source is loaded', () => {
57
57
  it('should not attach to the media control', () => {
58
- expect(bottomGear.addItem).not.toHaveBeenCalledWith('rate', expect.anything())
58
+ expect(bottomGear.addItem).not.toHaveBeenCalledWith(
59
+ 'rate',
60
+ expect.anything(),
61
+ )
59
62
  })
60
63
  })
61
64
  describe('after media source is loaded', () => {
@@ -67,11 +70,17 @@ describe('PlaybackRate', () => {
67
70
  core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
68
71
  })
69
72
  it('should not attach to the media control immediately', () => {
70
- expect(bottomGear.addItem).not.toHaveBeenCalledWith('rate', expect.anything())
73
+ expect(bottomGear.addItem).not.toHaveBeenCalledWith(
74
+ 'rate',
75
+ expect.anything(),
76
+ )
71
77
  })
72
78
  it('should attach to the media control after a short delay', async () => {
73
79
  await new Promise((resolve) => setTimeout(resolve, 25))
74
- expect(bottomGear.addItem).toHaveBeenCalledWith('rate', playbackRate.$el)
80
+ expect(bottomGear.addItem).toHaveBeenCalledWith(
81
+ 'rate',
82
+ playbackRate.$el,
83
+ )
75
84
  expect(
76
85
  bottomGear.$el.find('li[data-rate]').text(),
77
86
  // @ts-ignore
@@ -84,10 +93,13 @@ describe('PlaybackRate', () => {
84
93
  core.activeContainer.emit(Events.CONTAINER_LOADEDMETADATA)
85
94
  })
86
95
  it('should not attach to the media control', () => {
87
- expect(bottomGear.addItem).not.toHaveBeenCalledWith('rate', expect.anything())
96
+ expect(bottomGear.addItem).not.toHaveBeenCalledWith(
97
+ 'rate',
98
+ expect.anything(),
99
+ )
88
100
  })
89
101
  })
90
- });
102
+ })
91
103
  describe('on playback rate select', () => {
92
104
  beforeEach(async () => {
93
105
  core.activePlayback.dvrEnabled = true
@@ -159,7 +171,9 @@ describe('PlaybackRate', () => {
159
171
  playbackRate.$el.find('[data-rate="1.5"]').parent().hasClass('current'),
160
172
  ).toBe(true)
161
173
  expect(
162
- playbackRate.$el.find('[data-rate="1.5"]').hasClass('gcore-skin-active'),
174
+ playbackRate.$el
175
+ .find('[data-rate="1.5"]')
176
+ .hasClass('gcore-skin-active'),
163
177
  ).toBe(true)
164
178
  })
165
179
  it('should render proper gear box option label', () => {
@@ -175,11 +189,11 @@ expect.extend({
175
189
  toMatchPlaybackRateLabel(received, expected) {
176
190
  const { isNot } = this
177
191
  return {
178
- pass:
179
- received
180
- .replace(/\/assets.*\.svg/g, '')
181
- .replace(/\s+/g, ' ')
182
- .trim().includes(`playback_rate ${expected}`),
192
+ pass: received
193
+ .replace(/\/assets.*\.svg/g, '')
194
+ .replace(/\s+/g, ' ')
195
+ .trim()
196
+ .includes(`playback_rate ${expected}`),
183
197
  message: () => `${received} does${isNot ? '' : ' not'} match ${expected}`,
184
198
  }
185
199
  },
@@ -44,12 +44,9 @@ describe('Poster', () => {
44
44
  })
45
45
  describe('when playback is about to start', () => {
46
46
  describe.each([
47
- [
48
- Events.CONTAINER_STATE_BUFFERING,
49
- ], [
50
- Events.CONTAINER_STATE_BUFFERFULL,
51
- ]
52
- ])("event %s", (event) => {
47
+ [Events.CONTAINER_STATE_BUFFERING],
48
+ [Events.CONTAINER_STATE_BUFFERFULL],
49
+ ])('event %s', (event) => {
53
50
  beforeEach(() => {
54
51
  core.activeContainer.buffering = true
55
52
  core.activeContainer.trigger(event)
@@ -62,7 +59,7 @@ describe('Poster', () => {
62
59
  describe('when playback is started', () => {
63
60
  beforeEach(() => {
64
61
  core.activeContainer.trigger(Events.CONTAINER_PLAY)
65
- core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
62
+ core.activeContainer.playback.trigger(Events.PLAYBACK_PLAY)
66
63
  })
67
64
  it('should hide poster', () => {
68
65
  expect(poster.el.style.display).toBe('none')
@@ -78,7 +75,9 @@ describe('Poster', () => {
78
75
  expect(poster.el.style.display).not.toBe('none')
79
76
  })
80
77
  it('should show button', () => {
81
- expect(poster.$el.find('#poster-play')[0].style.display).not.toBe('none')
78
+ expect(poster.$el.find('#poster-play')[0].style.display).not.toBe(
79
+ 'none',
80
+ )
82
81
  })
83
82
  it('should add clickable class', () => {
84
83
  expect(poster.el.classList.contains('clickable')).toBe(true)
@@ -116,4 +115,4 @@ describe('Poster', () => {
116
115
  expect(poster.$el.find('#poster-play')[0].style.display).toBe('none')
117
116
  })
118
117
  })
119
- })
118
+ })
@@ -1,40 +1,40 @@
1
- import { Container, Events, UICorePlugin, template } from '@clappr/core';
1
+ import { Container, Events, UICorePlugin, template } from '@clappr/core'
2
2
 
3
- import { CLAPPR_VERSION } from '../../build.js';
3
+ import { CLAPPR_VERSION } from '../../build.js'
4
4
 
5
- import pluginHtml from '../../../assets/share/share.ejs';
6
- import '../../../assets/share/style.scss';
7
- import shareIcon from '../../../assets/icons/old/share.svg';
8
- import closeIcon from '../../../assets/icons/old/close-share.svg';
9
- import fbIcon from '../../../assets/icons/old/fb.svg';
10
- import twIcon from '../../../assets/icons/old/twitter.svg';
5
+ import pluginHtml from '../../../assets/share/share.ejs'
6
+ import '../../../assets/share/style.scss'
7
+ import shareIcon from '../../../assets/icons/old/share.svg'
8
+ import closeIcon from '../../../assets/icons/old/close-share.svg'
9
+ import fbIcon from '../../../assets/icons/old/fb.svg'
10
+ import twIcon from '../../../assets/icons/old/twitter.svg'
11
11
 
12
12
  /**
13
13
  * `PLUGIN` that adds a share button to the media control UI.
14
14
  * @beta
15
15
  */
16
16
  export class Share extends UICorePlugin {
17
- private hide = false;
17
+ private hide = false
18
18
 
19
- private container: Container | null = null;
19
+ private container: Container | null = null
20
20
 
21
21
  get name() {
22
- return 'share';
22
+ return 'share'
23
23
  }
24
24
 
25
25
  get supportedVersion() {
26
- return { min: CLAPPR_VERSION };
26
+ return { min: CLAPPR_VERSION }
27
27
  }
28
28
 
29
29
  get template() {
30
- return template(pluginHtml);
30
+ return template(pluginHtml)
31
31
  }
32
32
 
33
33
  override get attributes() {
34
34
  return {
35
- 'class': this.name + '_plugin',
36
- 'data-share': ''
37
- };
35
+ class: this.name + '_plugin',
36
+ 'data-share': '',
37
+ }
38
38
  }
39
39
 
40
40
  override get events() {
@@ -44,109 +44,134 @@ export class Share extends UICorePlugin {
44
44
  'click [data-share-fb]': 'onShareFB',
45
45
  'click [data-share-tw]': 'onShareTW',
46
46
  'click [data-share-link]': 'onShareLinkClick',
47
- 'click [data-share-embed]': 'onShareEmbedClick'
48
- };
47
+ 'click [data-share-embed]': 'onShareEmbedClick',
48
+ }
49
49
  }
50
50
 
51
51
  override bindEvents() {
52
- this.listenTo(this.core, Events.CORE_READY, this.onReady);
52
+ this.listenTo(this.core, Events.CORE_READY, this.onReady)
53
53
  // this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this.reload);
54
- this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_RENDERED, this.render);
55
- this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_HIDE, this.hideShare);
56
- this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_SHOW, this.showShare);
54
+ this.listenTo(
55
+ this.core.mediaControl,
56
+ Events.MEDIACONTROL_RENDERED,
57
+ this.render,
58
+ )
59
+ this.listenTo(
60
+ this.core.mediaControl,
61
+ Events.MEDIACONTROL_HIDE,
62
+ this.hideShare,
63
+ )
64
+ this.listenTo(
65
+ this.core.mediaControl,
66
+ Events.MEDIACONTROL_SHOW,
67
+ this.showShare,
68
+ )
57
69
  }
58
70
 
59
71
  unBindEvents() {
60
72
  // @ts-ignore
61
- this.stopListening(this.core, Events.CORE_READY);
73
+ this.stopListening(this.core, Events.CORE_READY)
62
74
  // @ts-ignore
63
75
  // this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED);
64
76
  // @ts-ignore
65
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_RENDERED);
77
+ this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_RENDERED)
66
78
  // @ts-ignore
67
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_HIDE);
79
+ this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_HIDE)
68
80
  // @ts-ignore
69
- this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_SHOW);
81
+ this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_SHOW)
70
82
  }
71
83
 
72
84
  canShowShare() {
73
- this.hide = false;
85
+ this.hide = false
74
86
  }
75
87
 
76
88
  private onReady() {
77
- this.hide = true;
78
- this.container = this.core.activeContainer;
89
+ this.hide = true
90
+ this.container = this.core.activeContainer
79
91
  if (this.container) {
80
- this.listenTo(this.container, 'container:settingsupdate', this.canShowShare);
92
+ this.listenTo(
93
+ this.container,
94
+ 'container:settingsupdate',
95
+ this.canShowShare,
96
+ )
81
97
  }
82
- this.hideShare();
98
+ this.hideShare()
83
99
  }
84
100
 
85
101
  override render() {
86
- this.$el.html(this.template({
87
- 'url':this.options.shareURL,
88
- 'embed': this.options.embed,
89
- 'embed_title': this.core.i18n.t('embed_title'),
90
- 'share_title': this.core.i18n.t('share_title'),
91
- 'link_title': this.core.i18n.t('link_title'),
92
- 'social_title': this.core.i18n.t('social_title'),
93
- }));
94
- this.core.mediaControl.$el.append(this.el);
95
- this.$el.find('.share-container').hide();
96
- this.initializeIcons();
97
-
98
- return this;
102
+ this.$el.html(
103
+ this.template({
104
+ url: this.options.shareURL,
105
+ embed: this.options.embed,
106
+ embed_title: this.core.i18n.t('embed_title'),
107
+ share_title: this.core.i18n.t('share_title'),
108
+ link_title: this.core.i18n.t('link_title'),
109
+ social_title: this.core.i18n.t('social_title'),
110
+ }),
111
+ )
112
+ this.core.mediaControl.$el.append(this.el)
113
+ this.$el.find('.share-container').hide()
114
+ this.initializeIcons()
115
+
116
+ return this
99
117
  }
100
118
 
101
119
  hideShare() {
102
- this.$el.addClass('share-hide');
120
+ this.$el.addClass('share-hide')
103
121
  }
104
122
 
105
123
  showShare() {
106
124
  if (this.hide) {
107
- return;
125
+ return
108
126
  }
109
- this.$el.removeClass('share-hide');
127
+ this.$el.removeClass('share-hide')
110
128
  }
111
129
 
112
130
  initializeIcons() {
113
- this.$el.find('button.media-control-button[data-share-button]')
131
+ this.$el
132
+ .find('button.media-control-button[data-share-button]')
114
133
  .addClass('gcore-skin-button-color')
115
- .append(shareIcon);
116
- this.$el.find('div.share-container-header--close').append(closeIcon);
117
- this.$el.find('div.share-container-header--socialicon_fb').append(fbIcon);
118
- this.$el.find('div.share-container-header--socialicon_tw').append(twIcon);
134
+ .append(shareIcon)
135
+ this.$el.find('div.share-container-header--close').append(closeIcon)
136
+ this.$el.find('div.share-container-header--socialicon_fb').append(fbIcon)
137
+ this.$el.find('div.share-container-header--socialicon_tw').append(twIcon)
119
138
  }
120
139
 
121
140
  onShareShow() {
122
- this.$el.find('.share-container').show();
141
+ this.$el.find('.share-container').show()
123
142
  }
124
143
 
125
144
  onShareHide() {
126
- this.$el.find('.share-container').hide();
145
+ this.$el.find('.share-container').hide()
127
146
  }
128
147
 
129
148
  onShareFB() {
130
149
  if (this.options.shareURL) {
131
- const url = 'https://www.facebook.com/sharer.php?u='+this.options.shareURL;
150
+ const url =
151
+ 'https://www.facebook.com/sharer.php?u=' + this.options.shareURL
132
152
 
133
- window.open(url, '_blank');
153
+ window.open(url, '_blank')
134
154
  }
135
155
  }
136
156
 
137
157
  onShareTW() {
138
158
  if (this.options.shareURL) {
139
- const url = 'https://twitter.com/intent/tweet?url='+this.options.shareURL;
159
+ const url =
160
+ 'https://twitter.com/intent/tweet?url=' + this.options.shareURL
140
161
 
141
- window.open(url, '_blank');
162
+ window.open(url, '_blank')
142
163
  }
143
164
  }
144
165
 
145
166
  onShareLinkClick() {
146
- this.$el.find('.share-container-header--link')[0].setSelectionRange(0, this.options.shareURL.length);
167
+ this.$el
168
+ .find('.share-container-header--link')[0]
169
+ .setSelectionRange(0, this.options.shareURL.length)
147
170
  }
148
171
 
149
172
  onShareEmbedClick() {
150
- this.$el.find('.share-container-header--embed')[0].setSelectionRange(0, this.options.embed.length);
173
+ this.$el
174
+ .find('.share-container-header--embed')[0]
175
+ .setSelectionRange(0, this.options.embed.length)
151
176
  }
152
177
  }
@@ -56,7 +56,11 @@ export class SkipTime extends UICorePlugin {
56
56
  */
57
57
  override bindEvents() {
58
58
  this.listenTo(this.core, Events.CORE_READY, this.render)
59
- this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged)
59
+ this.listenTo(
60
+ this.core,
61
+ Events.CORE_ACTIVE_CONTAINER_CHANGED,
62
+ this.onContainerChanged,
63
+ )
60
64
  }
61
65
 
62
66
  private onContainerChanged() {
@@ -166,11 +166,14 @@ export class SpinnerThreeBounce extends UIContainerPlugin {
166
166
  */
167
167
  override render() {
168
168
  this.$el.html(this.template())
169
- this.el.firstElementChild?.addEventListener('animationiteration', (event) => {
170
- this.trigger(SpinnerEvents.SYNC, {
171
- elapsedTime: (event as AnimationEvent).elapsedTime,
172
- })
173
- })
169
+ this.el.firstElementChild?.addEventListener(
170
+ 'animationiteration',
171
+ (event) => {
172
+ this.trigger(SpinnerEvents.SYNC, {
173
+ elapsedTime: (event as AnimationEvent).elapsedTime,
174
+ })
175
+ },
176
+ )
174
177
  this.container.$el.append(this.$el[0])
175
178
  if (this.container.buffering) {
176
179
  this._show()
@@ -132,11 +132,17 @@ export class ClosedCaptions extends UICorePlugin {
132
132
 
133
133
  private get preselectedLanguage(): string | undefined {
134
134
  return (
135
- this.core.options.cc?.language ??
136
- this.core.options.subtitles?.language
135
+ this.core.options.cc?.language ?? this.core.options.subtitles?.language
137
136
  )
138
137
  }
139
138
 
139
+ private isPreselectedLanguage(language: string): boolean {
140
+ if (!this.preselectedLanguage) {
141
+ return false
142
+ }
143
+ return language.startsWith(this.preselectedLanguage)
144
+ }
145
+
140
146
  /**
141
147
  * @internal
142
148
  */
@@ -228,12 +234,20 @@ export class ClosedCaptions extends UICorePlugin {
228
234
  this.mount()
229
235
  }
230
236
 
231
- private onSubtitleChanged({ id: _ }: { id: number }) {
237
+ private onSubtitleChanged({ id: changedId }: { id: number }) {
232
238
  // ignoring the subtitle selected by the playback engine or user agent
233
239
  const id = this.track?.id ?? -1
240
+ trace(`${T} onSubtitleChanged`, {
241
+ changedId,
242
+ id,
243
+ })
234
244
  if (id === -1) {
235
245
  this.clearSubtitleText()
236
246
  }
247
+ this.activateTrack(id)
248
+ }
249
+
250
+ private activateTrack(id: number) {
237
251
  for (const track of this.tracks) {
238
252
  if (track.id === id) {
239
253
  if (this.useNativeSubtitles) {
@@ -404,8 +418,12 @@ export class ClosedCaptions extends UICorePlugin {
404
418
  private selectItem(item: TextTrackItem | null) {
405
419
  this.clearSubtitleText()
406
420
  this.track = item
421
+ const trackId = item?.id ?? -1
422
+ this.core.activePlayback.closedCaptionsTrackId = trackId
407
423
 
408
424
  this.updateSelection()
425
+
426
+ this.activateTrack(trackId)
409
427
  }
410
428
 
411
429
  private onItemSelect(event: MouseEvent) {
@@ -427,8 +445,8 @@ export class ClosedCaptions extends UICorePlugin {
427
445
  // to hide the subtitles forcefully, set the language to 'none'
428
446
  setTimeout(() => {
429
447
  this.selectItem(
430
- this.tracks.find(
431
- (t) => t.track.language === this.preselectedLanguage,
448
+ this.tracks.find((t) =>
449
+ this.isPreselectedLanguage(t.track.language),
432
450
  ) ?? null,
433
451
  )
434
452
  }, 0)
@@ -551,7 +569,13 @@ export class ClosedCaptions extends UICorePlugin {
551
569
  }
552
570
 
553
571
  private get useNativeSubtitles() {
554
- const mode = this.core.options.cc?.mode ?? this.core.options.subtitles?.mode ?? 'custom'
572
+ if (this.core.activePlayback?.name === 'dash') {
573
+ return true
574
+ }
575
+ const mode =
576
+ this.core.options.cc?.mode ??
577
+ this.core.options.subtitles?.mode ??
578
+ 'custom'
555
579
  // TODO or Safari? or iOS?
556
580
  return mode === 'native'
557
581
  }
@@ -173,7 +173,6 @@ describe('ClosedCaptions', () => {
173
173
  // TODO test explicitly that PLAYBACK_SUBTITLE_CHANGED event does not cause track switch
174
174
  core.activePlayback.emit(Events.PLAYBACK_SUBTITLE_CHANGED, { id: 2 })
175
175
  await new Promise((resolve) => setTimeout(resolve, 100))
176
-
177
176
  })
178
177
  it('should activate selected track', () => {
179
178
  expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
@@ -235,10 +234,10 @@ describe('ClosedCaptions', () => {
235
234
  it('should deactivate subtitle track', () => {
236
235
  expect(core.activePlayback.closedCaptionsTrackId).toEqual(-1)
237
236
  expect(core.activePlayback.closedCaptionsTracks[0].track.mode).toBe(
238
- 'hidden',
237
+ 'disabled',
239
238
  )
240
239
  expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
241
- 'hidden',
240
+ 'disabled',
242
241
  )
243
242
  })
244
243
  it('should select menu item', () => {