@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.
- package/dist/core.js +45 -32
- package/dist/index.css +305 -305
- package/dist/index.embed.js +119 -40
- package/dist/index.js +255 -124
- 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/dash-playback/DashPlayback.d.ts +4 -0
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +7 -0
- 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 +2 -0
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.js +25 -5
- 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 +2 -2
- package/src/Player.ts +10 -10
- package/src/__tests__/Player.test.ts +33 -10
- package/src/index.core.ts +9 -1
- package/src/index.plugins.ts +35 -35
- package/src/playback/__tests__/HTML5Video.test.ts +10 -4
- package/src/playback/dash-playback/DashPlayback.ts +8 -0
- 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 +30 -6
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +2 -3
- 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,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:
|
|
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
|
|
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
|
-
|
|
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
|
-
'
|
|
237
|
+
'disabled',
|
|
239
238
|
)
|
|
240
239
|
expect(core.activePlayback.closedCaptionsTracks[1].track.mode).toBe(
|
|
241
|
-
'
|
|
240
|
+
'disabled',
|
|
242
241
|
)
|
|
243
242
|
})
|
|
244
243
|
it('should select menu item', () => {
|