@gcorevideo/player 2.28.25 → 2.28.27
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.
- package/dist/core.js +166 -61
- package/dist/index.css +395 -395
- package/dist/index.embed.js +155 -66
- package/dist/index.js +355 -151
- package/lib/Player.d.ts.map +1 -1
- package/lib/index.core.d.ts +1 -1
- package/lib/index.core.d.ts.map +1 -1
- package/lib/index.core.js +1 -1
- package/lib/index.plugins.d.ts +34 -34
- package/lib/index.plugins.d.ts.map +1 -1
- package/lib/index.plugins.js +34 -34
- package/lib/playback/types.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +3 -1
- package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/speedtest/index.js +9 -5
- package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/utils.d.ts +2 -2
- package/lib/plugins/clips/utils.d.ts.map +1 -1
- package/lib/plugins/cmcd-config/CmcdConfig.js +1 -1
- package/lib/plugins/favicon/Favicon.d.ts.map +1 -1
- package/lib/plugins/google-analytics/GoogleAnalytics.d.ts.map +1 -1
- package/lib/plugins/google-analytics/GoogleAnalytics.js +10 -3
- package/lib/plugins/kibo/index.d.ts.map +1 -1
- package/lib/plugins/kibo/index.js +69 -20
- package/lib/plugins/level-selector/QualityLevels.js +2 -2
- package/lib/plugins/logo/Logo.d.ts.map +1 -1
- package/lib/plugins/logo/Logo.js +19 -15
- package/lib/plugins/logo/utils/index.d.ts.map +1 -1
- package/lib/plugins/logo/utils/index.js +11 -7
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -1
- package/lib/plugins/multi-camera/MultiCamera.js +42 -20
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +3 -2
- package/lib/plugins/share/Share.d.ts.map +1 -1
- package/lib/plugins/share/Share.js +17 -12
- package/lib/plugins/skip-time/SkipTime.d.ts.map +1 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.js +4 -3
- package/lib/plugins/thumbnails/Thumbnails.js +2 -3
- package/lib/plugins/thumbnails/utils.d.ts.map +1 -1
- package/lib/plugins/utils/fullscreen.d.ts.map +1 -1
- package/lib/plugins/utils.d.ts.map +1 -1
- package/lib/plugins/utils.js +1 -1
- package/lib/plugins/vast-ads/VastAds.d.ts.map +1 -1
- package/lib/plugins/vast-ads/VastAds.js +2 -1
- package/lib/plugins/vast-ads/loaderxml.d.ts.map +1 -1
- package/lib/plugins/vast-ads/loaderxml.js +8 -5
- package/lib/plugins/vast-ads/roll.d.ts +2 -2
- package/lib/plugins/vast-ads/roll.d.ts.map +1 -1
- package/lib/plugins/vast-ads/roll.js +16 -10
- package/lib/plugins/vast-ads/rollmanager.d.ts.map +1 -1
- package/lib/plugins/vast-ads/rollmanager.js +17 -7
- package/lib/plugins/vast-ads/sctemanager.d.ts +1 -1
- package/lib/plugins/vast-ads/sctemanager.d.ts.map +1 -1
- package/lib/plugins/vast-ads/sctemanager.js +6 -5
- package/lib/plugins/vast-ads/types.d.ts.map +1 -1
- package/lib/plugins/vast-ads/urlhandler.d.ts.map +1 -1
- package/lib/plugins/vast-ads/xmlhttprequest.d.ts.map +1 -1
- package/lib/plugins/vast-ads/xmlhttprequest.js +3 -2
- package/lib/plugins/vast-ads/xmlmerge.d.ts.map +1 -1
- package/lib/plugins/vast-ads/xmlmerge.js +4 -3
- package/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/clickaway.d.ts.map +1 -1
- package/lib/utils/mediaSources.d.ts.map +1 -1
- package/lib/utils/mediaSources.js +1 -3
- package/lib/utils/types.d.ts.map +1 -1
- package/lib/version.js +2 -2
- package/package.json +3 -3
- package/src/Player.ts +10 -10
- package/src/__tests__/Player.test.ts +33 -10
- package/src/index.core.ts +10 -1
- package/src/index.plugins.ts +35 -35
- package/src/playback/BasePlayback.ts +1 -1
- package/src/playback/__tests__/HTML5Video.test.ts +10 -4
- package/src/playback/dash-playback/__tests__/DashPlayback.test.ts +10 -38
- package/src/playback/hls-playback/__tests__/HlsPlayback.test.ts +12 -45
- package/src/playback/types.ts +0 -1
- package/src/playback.types.ts +1 -2
- package/src/plugins/audio-selector/AudioTracks.ts +1 -1
- package/src/plugins/audio-selector/__tests__/AudioTracks.test.ts +30 -11
- package/src/plugins/bottom-gear/BottomGear.ts +3 -2
- package/src/plugins/clappr-nerd-stats/NerdStats.ts +1 -1
- package/src/plugins/clappr-nerd-stats/speedtest/index.ts +104 -82
- package/src/plugins/clappr-nerd-stats/speedtest/types.ts +3 -3
- package/src/plugins/clappr-nerd-stats/utils.ts +2 -2
- package/src/plugins/clappr-stats/__tests__/ClapprStats.test.ts +30 -18
- package/src/plugins/clips/utils.ts +5 -1
- package/src/plugins/cmcd-config/CmcdConfig.ts +1 -1
- package/src/plugins/error-screen/__tests__/ErrorScreen.test.ts +21 -15
- package/src/plugins/favicon/Favicon.ts +73 -49
- package/src/plugins/google-analytics/GoogleAnalytics.ts +93 -58
- package/src/plugins/kibo/index.ts +183 -109
- package/src/plugins/level-selector/QualityLevels.ts +2 -2
- package/src/plugins/logo/Logo.ts +134 -105
- package/src/plugins/logo/utils/index.ts +27 -20
- package/src/plugins/media-control/MediaControl.ts +12 -6
- package/src/plugins/multi-camera/MultiCamera.ts +218 -157
- package/src/plugins/picture-in-picture/PictureInPicture.ts +41 -37
- package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +25 -11
- package/src/plugins/poster/__tests__/Poster.test.ts +8 -9
- package/src/plugins/share/Share.ts +85 -60
- package/src/plugins/skip-time/SkipTime.ts +5 -1
- package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +8 -5
- package/src/plugins/subtitles/ClosedCaptions.ts +7 -5
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +0 -1
- package/src/plugins/thumbnails/Thumbnails.ts +22 -21
- package/src/plugins/thumbnails/__tests__/Thumbnails.test.ts +14 -7
- package/src/plugins/thumbnails/utils.ts +3 -1
- package/src/plugins/typings/globals.d.ts +7 -7
- package/src/plugins/typings/workers.d.ts +3 -3
- package/src/plugins/utils/fullscreen.ts +2 -2
- package/src/plugins/utils.ts +17 -13
- package/src/plugins/vast-ads/VastAds.ts +4 -5
- package/src/plugins/vast-ads/loaderxml.ts +142 -101
- package/src/plugins/vast-ads/roll.ts +381 -284
- package/src/plugins/vast-ads/rollmanager.ts +214 -170
- package/src/plugins/vast-ads/sctemanager.ts +66 -48
- package/src/plugins/vast-ads/types.ts +15 -9
- package/src/plugins/vast-ads/urlhandler.ts +18 -13
- package/src/plugins/vast-ads/xmlhttprequest.ts +25 -20
- package/src/plugins/vast-ads/xmlmerge.ts +42 -32
- package/src/plugins/video360/VRControls.js +50 -42
- package/src/plugins/video360/VREffect.js +298 -206
- package/src/plugins/video360/Video360.js +553 -423
- package/src/plugins/video360/orbit-oriention-controls.js +526 -421
- package/src/plugins/video360/utils.js +18 -18
- package/src/types.ts +5 -3
- package/src/typings/@clappr/core/error_mixin.d.ts +9 -9
- package/src/typings/@clappr/core/index.d.ts +1 -3
- package/src/typings/@clappr/core/playback.d.ts +3 -3
- package/src/typings/@clappr/index.d.ts +1 -1
- package/src/typings/globals.d.ts +15 -15
- package/src/utils/__tests__/mediaSources.test.ts +42 -26
- package/src/utils/clickaway.ts +24 -24
- package/src/utils/errors.ts +2 -2
- package/src/utils/mediaSources.ts +5 -4
- package/src/utils/types.ts +1 -1
- package/src/version.ts +2 -2
- 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
|
-
|
|
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:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
55
|
-
|
|
56
|
-
|
|
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(
|
|
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(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this.
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
170
|
-
|
|
171
|
-
|
|
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,8 +132,7 @@ 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
|
|
|
@@ -446,8 +445,8 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
446
445
|
// to hide the subtitles forcefully, set the language to 'none'
|
|
447
446
|
setTimeout(() => {
|
|
448
447
|
this.selectItem(
|
|
449
|
-
this.tracks.find(
|
|
450
|
-
|
|
448
|
+
this.tracks.find((t) =>
|
|
449
|
+
this.isPreselectedLanguage(t.track.language),
|
|
451
450
|
) ?? null,
|
|
452
451
|
)
|
|
453
452
|
}, 0)
|
|
@@ -573,7 +572,10 @@ export class ClosedCaptions extends UICorePlugin {
|
|
|
573
572
|
if (this.core.activePlayback?.name === 'dash') {
|
|
574
573
|
return true
|
|
575
574
|
}
|
|
576
|
-
const mode =
|
|
575
|
+
const mode =
|
|
576
|
+
this.core.options.cc?.mode ??
|
|
577
|
+
this.core.options.subtitles?.mode ??
|
|
578
|
+
'custom'
|
|
577
579
|
// TODO or Safari? or iOS?
|
|
578
580
|
return mode === 'native'
|
|
579
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(
|
|
@@ -523,34 +523,35 @@ export class Thumbnails extends UICorePlugin {
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
type ParsedVTT = {
|
|
526
|
-
id: string
|
|
527
|
-
start: number
|
|
528
|
-
end: number
|
|
529
|
-
text: string
|
|
526
|
+
id: string
|
|
527
|
+
start: number
|
|
528
|
+
end: number
|
|
529
|
+
text: string
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
-
|
|
533
532
|
function parseVTT(vtt: string): ParsedVTT[] {
|
|
534
|
-
const correctedVTT = (
|
|
535
|
-
.
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
533
|
+
const correctedVTT = (
|
|
534
|
+
vtt.startsWith('WEBVTT') ? vtt : 'WEBVTT\n\n' + vtt
|
|
535
|
+
).replace(/(\d+:\d+:\d+),(\d+)/g, '$1.$2')
|
|
536
|
+
const parser = new WebVTT.Parser(window)
|
|
537
|
+
const cues: ParsedVTT[] = []
|
|
538
|
+
;(parser as any).oncue = (cue: any) => {
|
|
539
539
|
cues.push({
|
|
540
540
|
id: cue.id,
|
|
541
541
|
start: cue.startTime,
|
|
542
542
|
end: cue.endTime,
|
|
543
|
-
text: cue.text
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
(parser as any).onparsingerror = reportError
|
|
543
|
+
text: cue.text,
|
|
544
|
+
})
|
|
545
|
+
}
|
|
546
|
+
;(parser as any).onparsingerror = reportError
|
|
547
547
|
|
|
548
548
|
// TextEncoder is available in all modern browsers and Node >=v11
|
|
549
|
-
const uint8Array =
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
parser.
|
|
554
|
-
|
|
555
|
-
|
|
549
|
+
const uint8Array =
|
|
550
|
+
typeof TextEncoder !== 'undefined'
|
|
551
|
+
? new TextEncoder().encode(correctedVTT)
|
|
552
|
+
: Buffer.from(correctedVTT, 'utf-8')
|
|
553
|
+
parser.parse(uint8Array as any)
|
|
554
|
+
parser.flush()
|
|
555
|
+
|
|
556
|
+
return cues
|
|
556
557
|
}
|