@gcorevideo/player 2.21.1 → 2.21.4
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/assets/audio-selector/style.scss +1 -1
- package/assets/audio-selector/track-selector.ejs +3 -3
- package/assets/bottom-gear/bottomgear.ejs +2 -2
- package/assets/media-control/container.scss +1 -1
- package/assets/media-control/media-control.ejs +1 -11
- package/assets/media-control/media-control.scss +49 -57
- package/assets/media-control/width270.scss +1 -1
- package/assets/media-control/width370.scss +7 -9
- package/assets/playback-rate/button.ejs +2 -2
- package/assets/playback-rate/list.ejs +4 -4
- package/assets/subtitles/combobox.ejs +10 -12
- package/assets/subtitles/string.ejs +1 -1
- package/assets/subtitles/style.scss +9 -16
- package/dist/core.js +5 -1
- package/dist/index.css +782 -794
- package/dist/index.js +240 -244
- package/dist/player.d.ts +141 -119
- package/dist/plugins/index.css +862 -874
- package/dist/plugins/index.js +222 -238
- package/docs/api/player.bottomgear.getelement.md +2 -2
- package/docs/api/player.bottomgear.md +1 -1
- package/docs/api/{player.subtitles.hide.md → player.closedcaptions.hide.md} +2 -2
- package/docs/api/{player.subtitles.md → player.closedcaptions.md} +11 -11
- package/docs/api/{player.subtitles.show.md → player.closedcaptions.show.md} +2 -2
- package/docs/api/player.closedcaptionspluginsettings.md +13 -0
- package/docs/api/player.gearitemelement.md +6 -4
- package/docs/api/player.gearoptionsitem.md +16 -0
- package/docs/api/player.md +48 -12
- package/docs/api/player.mediacontrol.putelement.md +2 -2
- package/docs/api/player.mediacontrolelement.md +1 -1
- package/docs/api/player.playbackrate.md +1 -1
- package/docs/api/player.subtitlespluginsettings.md +18 -0
- package/docs/api/player.texttrackitem.id.md +11 -0
- package/docs/api/player.texttrackitem.md +87 -0
- package/docs/api/player.texttrackitem.name.md +11 -0
- package/docs/api/player.texttrackitem.track.md +11 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/index.plugins.d.ts +2 -1
- package/lib/index.plugins.d.ts.map +1 -1
- package/lib/index.plugins.js +2 -1
- package/lib/playback/BasePlayback.d.ts +1 -0
- package/lib/playback/BasePlayback.d.ts.map +1 -1
- package/lib/playback/BasePlayback.js +3 -0
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +1 -0
- package/lib/playback.types.d.ts +5 -0
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/plugins/audio-selector/AudioSelector.d.ts +2 -3
- package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
- package/lib/plugins/audio-selector/AudioSelector.js +6 -7
- package/lib/plugins/bottom-gear/BottomGear.d.ts +7 -3
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +4 -2
- package/lib/plugins/media-control/MediaControl.d.ts +5 -6
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +48 -39
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -0
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +4 -4
- package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.js +24 -14
- package/lib/plugins/subtitles/ClosedCaptions.d.ts +118 -0
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -0
- package/lib/plugins/subtitles/ClosedCaptions.js +348 -0
- package/lib/plugins/subtitles/Subtitles.d.ts +31 -26
- package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
- package/lib/plugins/subtitles/Subtitles.js +138 -169
- package/lib/testUtils.d.ts +22 -18
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +22 -36
- package/package.json +1 -1
- package/src/index.plugins.ts +2 -1
- package/src/index.ts +1 -1
- package/src/playback/BasePlayback.ts +4 -0
- package/src/playback/dash-playback/DashPlayback.ts +1 -0
- package/src/playback.types.ts +6 -0
- package/src/plugins/audio-selector/AudioSelector.ts +9 -8
- package/src/plugins/bottom-gear/BottomGear.ts +14 -5
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -1
- package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +2 -2
- package/src/plugins/media-control/MediaControl.ts +84 -60
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +43 -0
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +175 -0
- package/src/plugins/picture-in-picture/PictureInPicture.ts +5 -5
- package/src/plugins/playback-rate/PlaybackRate.ts +143 -100
- package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +65 -0
- package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +11 -0
- package/src/plugins/subtitles/ClosedCaptions.ts +469 -0
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +58 -0
- package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +25 -0
- package/src/testUtils.ts +22 -36
- package/temp/player.api.json +269 -89
- package/tsconfig.tsbuildinfo +1 -1
- package/src/plugins/index.ts +0 -39
- package/src/plugins/subtitles/Subtitles.ts +0 -496
|
@@ -43,6 +43,8 @@ export class PictureInPicture extends UICorePlugin {
|
|
|
43
43
|
return VERSION;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
private static buttonTemplate = template(buttonHtml);
|
|
47
|
+
|
|
46
48
|
/**
|
|
47
49
|
* @internal
|
|
48
50
|
*/
|
|
@@ -71,8 +73,8 @@ export class PictureInPicture extends UICorePlugin {
|
|
|
71
73
|
|
|
72
74
|
private isPiPSupported() {
|
|
73
75
|
trace(`${T} isPiPSupported`, {
|
|
74
|
-
pictureInPictureEnabled: document.pictureInPictureEnabled,
|
|
75
|
-
requestPictureInPicture: HTMLVideoElement.prototype.requestPictureInPicture,
|
|
76
|
+
pictureInPictureEnabled: !!document.pictureInPictureEnabled,
|
|
77
|
+
requestPictureInPicture: !!HTMLVideoElement.prototype.requestPictureInPicture,
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
return document.pictureInPictureEnabled && !!HTMLVideoElement.prototype.requestPictureInPicture;
|
|
@@ -86,9 +88,7 @@ export class PictureInPicture extends UICorePlugin {
|
|
|
86
88
|
return this;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
this.$el.html(t({ pipIcon }));
|
|
91
|
+
this.$el.html(PictureInPicture.buttonTemplate({ pipIcon }));
|
|
92
92
|
|
|
93
93
|
const mediaControl = this.core.getPlugin('media_control');
|
|
94
94
|
if (mediaControl) {
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import { Events, UICorePlugin, Playback, template, Core } from '@clappr/core'
|
|
2
|
-
import { trace } from '@gcorevideo/utils'
|
|
3
|
-
import assert from 'assert'
|
|
4
|
-
|
|
5
|
-
import { CLAPPR_VERSION } from '../../build.js'
|
|
6
|
-
import type { ZeptoResult } from '../../types.js'
|
|
7
|
-
|
|
8
|
-
import buttonHtml from '../../../assets/playback-rate/button.ejs'
|
|
9
|
-
import listHtml from '../../../assets/playback-rate/list.ejs'
|
|
10
|
-
import speedIcon from '../../../assets/icons/new/speed.svg'
|
|
11
|
-
import arrowRightIcon from '../../../assets/icons/new/arrow-right.svg'
|
|
12
|
-
import arrowLeftIcon from '../../../assets/icons/new/arrow-left.svg'
|
|
13
|
-
import checkIcon from '../../../assets/icons/new/check.svg'
|
|
14
|
-
import { BottomGear } from '../bottom-gear/BottomGear.js'
|
|
15
|
-
import { PlaybackEvents } from '../../playback/types.js'
|
|
16
|
-
import {
|
|
1
|
+
import { Events, UICorePlugin, Playback, template, Core } from '@clappr/core'
|
|
2
|
+
import { trace } from '@gcorevideo/utils'
|
|
3
|
+
import assert from 'assert'
|
|
4
|
+
|
|
5
|
+
import { CLAPPR_VERSION } from '../../build.js'
|
|
6
|
+
import type { ZeptoResult } from '../../types.js'
|
|
7
|
+
|
|
8
|
+
import buttonHtml from '../../../assets/playback-rate/button.ejs'
|
|
9
|
+
import listHtml from '../../../assets/playback-rate/list.ejs'
|
|
10
|
+
import speedIcon from '../../../assets/icons/new/speed.svg'
|
|
11
|
+
import arrowRightIcon from '../../../assets/icons/new/arrow-right.svg'
|
|
12
|
+
import arrowLeftIcon from '../../../assets/icons/new/arrow-left.svg'
|
|
13
|
+
import checkIcon from '../../../assets/icons/new/check.svg'
|
|
14
|
+
import { BottomGear } from '../bottom-gear/BottomGear.js'
|
|
15
|
+
import { PlaybackEvents } from '../../playback/types.js'
|
|
16
|
+
import {
|
|
17
|
+
MediaControl,
|
|
18
|
+
MediaControlEvents,
|
|
19
|
+
} from '../media-control/MediaControl.js'
|
|
17
20
|
|
|
18
21
|
type PlaybackRateOption = {
|
|
19
|
-
value: string
|
|
20
|
-
label: string
|
|
22
|
+
value: string
|
|
23
|
+
label: string
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
const DEFAULT_PLAYBACK_RATES = [
|
|
@@ -27,12 +30,12 @@ const DEFAULT_PLAYBACK_RATES = [
|
|
|
27
30
|
{ value: '1.25', label: '1.25x' },
|
|
28
31
|
{ value: '1.5', label: '1.5x' },
|
|
29
32
|
{ value: '1.75', label: '1.75x' },
|
|
30
|
-
{ value: '2.0', label: '2x' }
|
|
31
|
-
]
|
|
33
|
+
{ value: '2.0', label: '2x' },
|
|
34
|
+
]
|
|
32
35
|
|
|
33
|
-
const DEFAULT_PLAYBACK_RATE = '1.0'
|
|
36
|
+
const DEFAULT_PLAYBACK_RATE = '1.0'
|
|
34
37
|
|
|
35
|
-
const T = 'plugins.playback_rate'
|
|
38
|
+
const T = 'plugins.playback_rate'
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* `PLUGIN` that allows changing the playback speed of the video.
|
|
@@ -46,39 +49,42 @@ const T = 'plugins.playback_rate';
|
|
|
46
49
|
* - {@link BottomGear | bottom_gear}
|
|
47
50
|
*
|
|
48
51
|
* It renders a button in the gear menu, which opens a dropdown with the options to change the playback rate.
|
|
52
|
+
* Note that the playback rate change is supported only for VOD or DVR enabled live streams.
|
|
49
53
|
*/
|
|
50
54
|
export class PlaybackRate extends UICorePlugin {
|
|
51
|
-
private playbackRates: PlaybackRateOption[] = DEFAULT_PLAYBACK_RATES
|
|
55
|
+
private playbackRates: PlaybackRateOption[] = DEFAULT_PLAYBACK_RATES
|
|
52
56
|
|
|
53
57
|
// Saved when an ad starts to restore after it finishes
|
|
54
|
-
private prevSelectedRate: string | undefined
|
|
58
|
+
private prevSelectedRate: string | undefined
|
|
55
59
|
|
|
56
|
-
private rendered = false
|
|
60
|
+
private rendered = false
|
|
57
61
|
|
|
58
|
-
private selectedRate: string = DEFAULT_PLAYBACK_RATE
|
|
62
|
+
private selectedRate: string = DEFAULT_PLAYBACK_RATE
|
|
59
63
|
|
|
60
64
|
/**
|
|
61
65
|
* @internal
|
|
62
66
|
*/
|
|
63
67
|
get name() {
|
|
64
|
-
return 'playback_rate'
|
|
68
|
+
return 'playback_rate'
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
/**
|
|
68
72
|
* @internal
|
|
69
73
|
*/
|
|
70
74
|
get supportedVersion() {
|
|
71
|
-
return { min: CLAPPR_VERSION }
|
|
75
|
+
return { min: CLAPPR_VERSION }
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
private static readonly buttonTemplate = template(buttonHtml)
|
|
78
|
+
private static readonly buttonTemplate = template(buttonHtml)
|
|
75
79
|
|
|
76
|
-
private static readonly listTemplate = template(listHtml)
|
|
80
|
+
private static readonly listTemplate = template(listHtml)
|
|
77
81
|
|
|
78
82
|
constructor(core: Core) {
|
|
79
|
-
super(core)
|
|
80
|
-
this.playbackRates =
|
|
81
|
-
|
|
83
|
+
super(core)
|
|
84
|
+
this.playbackRates =
|
|
85
|
+
core.options.playbackRate?.options || DEFAULT_PLAYBACK_RATES
|
|
86
|
+
this.selectedRate =
|
|
87
|
+
core.options.playbackRate?.defaultValue || DEFAULT_PLAYBACK_RATE
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
/**
|
|
@@ -86,9 +92,8 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
86
92
|
*/
|
|
87
93
|
override get attributes() {
|
|
88
94
|
return {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
95
|
+
class: 'media-control-playbackrate',
|
|
96
|
+
}
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
/**
|
|
@@ -99,38 +104,56 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
99
104
|
'click .gear-sub-menu_btn': 'onRateSelect',
|
|
100
105
|
'click .gear-option': 'onShowMenu',
|
|
101
106
|
'click .go-back': 'goBack',
|
|
102
|
-
}
|
|
107
|
+
}
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
/**
|
|
106
111
|
* @internal
|
|
107
112
|
*/
|
|
108
113
|
override bindEvents() {
|
|
109
|
-
this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
|
|
110
|
-
this.listenTo(
|
|
114
|
+
this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
|
|
115
|
+
this.listenTo(
|
|
116
|
+
this.core,
|
|
117
|
+
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
118
|
+
this.onActiveContainerChange,
|
|
119
|
+
)
|
|
111
120
|
}
|
|
112
121
|
|
|
113
122
|
private onCoreReady() {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
trace(`${T} onCoreReady`)
|
|
124
|
+
const mediaControl = this.core.getPlugin('media_control')
|
|
125
|
+
assert(mediaControl, 'media_control plugin is required')
|
|
126
|
+
const gear = this.core.getPlugin('bottom_gear') as BottomGear
|
|
127
|
+
assert(gear, 'bottom_gear plugin is required')
|
|
128
|
+
this.listenTo(
|
|
129
|
+
mediaControl,
|
|
130
|
+
MediaControlEvents.MEDIACONTROL_GEAR_RENDERED,
|
|
131
|
+
this.onGearRendered,
|
|
132
|
+
)
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
private onActiveContainerChange() {
|
|
122
|
-
|
|
123
|
-
this.listenTo(this.core.activePlayback, Events.
|
|
124
|
-
this.listenTo(this.core.activePlayback,
|
|
125
|
-
this.listenTo(
|
|
136
|
+
trace(`${T} onActiveContainerChange`)
|
|
137
|
+
this.listenTo(this.core.activePlayback, Events.PLAYBACK_STOP, this.onStop)
|
|
138
|
+
this.listenTo(this.core.activePlayback, Events.PLAYBACK_PLAY, this.onPlay)
|
|
139
|
+
this.listenTo(
|
|
140
|
+
this.core.activePlayback,
|
|
141
|
+
PlaybackEvents.PLAYBACK_RATE_CHANGED,
|
|
142
|
+
this.onPlaybackRateChange,
|
|
143
|
+
)
|
|
144
|
+
this.listenTo(
|
|
145
|
+
this.core.activeContainer,
|
|
146
|
+
Events.CONTAINER_PLAYBACKDVRSTATECHANGED,
|
|
147
|
+
this.onDvrStateChanged,
|
|
148
|
+
)
|
|
126
149
|
}
|
|
127
150
|
|
|
128
151
|
private onGearRendered() {
|
|
129
152
|
trace(`${T} onGearRendered`, {
|
|
130
153
|
rendered: this.rendered,
|
|
131
|
-
})
|
|
132
|
-
this.rendered = false
|
|
133
|
-
this.render()
|
|
154
|
+
})
|
|
155
|
+
this.rendered = false
|
|
156
|
+
this.render()
|
|
134
157
|
}
|
|
135
158
|
|
|
136
159
|
private onDvrStateChanged(dvrEnabled: boolean) {
|
|
@@ -138,40 +161,45 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
138
161
|
dvrEnabled,
|
|
139
162
|
})
|
|
140
163
|
if (dvrEnabled) {
|
|
141
|
-
this.render()
|
|
164
|
+
this.render()
|
|
142
165
|
}
|
|
143
166
|
}
|
|
144
167
|
|
|
145
168
|
private allRateElements(): ZeptoResult {
|
|
146
|
-
return this.$('ul.gear-sub-menu li')
|
|
169
|
+
return this.$('ul.gear-sub-menu li')
|
|
147
170
|
}
|
|
148
171
|
|
|
149
|
-
private rateElement(rate =
|
|
150
|
-
return (
|
|
172
|
+
private rateElement(rate = '1'): ZeptoResult {
|
|
173
|
+
return (
|
|
174
|
+
this.$(`ul.gear-sub-menu a[data-rate="${rate}"]`) as ZeptoResult
|
|
175
|
+
).parent()
|
|
151
176
|
}
|
|
152
177
|
|
|
153
178
|
private onPlaybackRateChange(playbackRate: number) {
|
|
154
|
-
const selectedRate = parseInt(this.selectedRate, 10)
|
|
179
|
+
const selectedRate = parseInt(this.selectedRate, 10)
|
|
155
180
|
// TODO check it doesn't interfere with the DASH.js or HLS.js playback live catchup
|
|
156
181
|
if (Math.abs(playbackRate - selectedRate) > 0.1) {
|
|
157
182
|
trace(`${T} onPlaybackRateChange setting target rate`, {
|
|
158
183
|
playbackRate,
|
|
159
184
|
selectedRate,
|
|
160
185
|
})
|
|
161
|
-
this.core.activePlayback?.setPlaybackRate(selectedRate)
|
|
186
|
+
this.core.activePlayback?.setPlaybackRate(selectedRate)
|
|
162
187
|
}
|
|
163
188
|
}
|
|
164
189
|
|
|
165
190
|
private shouldRender() {
|
|
166
|
-
if (!this.core.
|
|
167
|
-
return false
|
|
191
|
+
if (!this.core.activePlayback) {
|
|
192
|
+
return false
|
|
168
193
|
}
|
|
169
194
|
|
|
170
|
-
if (
|
|
171
|
-
|
|
195
|
+
if (
|
|
196
|
+
this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
|
|
197
|
+
!this.core.activePlayback.dvrEnabled
|
|
198
|
+
) {
|
|
199
|
+
return false
|
|
172
200
|
}
|
|
173
201
|
|
|
174
|
-
return 'setPlaybackRate' in this.core.activePlayback
|
|
202
|
+
return 'setPlaybackRate' in this.core.activePlayback
|
|
175
203
|
}
|
|
176
204
|
|
|
177
205
|
/**
|
|
@@ -184,99 +212,114 @@ export class PlaybackRate extends UICorePlugin {
|
|
|
184
212
|
})
|
|
185
213
|
|
|
186
214
|
if (!this.shouldRender()) {
|
|
187
|
-
return this
|
|
215
|
+
return this
|
|
188
216
|
}
|
|
189
217
|
|
|
190
218
|
if (this.rendered) {
|
|
191
|
-
return this
|
|
219
|
+
return this
|
|
192
220
|
}
|
|
193
221
|
|
|
194
222
|
const button = PlaybackRate.buttonTemplate({
|
|
195
223
|
title: this.getTitle(),
|
|
196
224
|
speedIcon,
|
|
197
225
|
arrowRightIcon,
|
|
198
|
-
|
|
226
|
+
i18n: this.core.i18n,
|
|
227
|
+
})
|
|
199
228
|
|
|
200
|
-
this.$el.html(button)
|
|
229
|
+
this.$el.html(button)
|
|
201
230
|
|
|
202
|
-
(this.core.getPlugin('bottom_gear') as BottomGear)
|
|
231
|
+
;(this.core.getPlugin('bottom_gear') as BottomGear)
|
|
232
|
+
?.getElement('rate')
|
|
233
|
+
?.html(this.el)
|
|
203
234
|
|
|
204
|
-
this.rendered = true
|
|
235
|
+
this.rendered = true
|
|
205
236
|
|
|
206
|
-
return this
|
|
237
|
+
return this
|
|
207
238
|
}
|
|
208
239
|
|
|
209
240
|
private onStartAd() {
|
|
210
|
-
this.prevSelectedRate = this.selectedRate
|
|
211
|
-
this.resetPlaybackRate()
|
|
212
|
-
this.listenToOnce(
|
|
241
|
+
this.prevSelectedRate = this.selectedRate
|
|
242
|
+
this.resetPlaybackRate()
|
|
243
|
+
this.listenToOnce(
|
|
244
|
+
this.core.activePlayback,
|
|
245
|
+
Events.PLAYBACK_PLAY,
|
|
246
|
+
this.onFinishAd,
|
|
247
|
+
)
|
|
213
248
|
}
|
|
214
249
|
|
|
215
250
|
private onFinishAd() {
|
|
216
251
|
if (this.prevSelectedRate) {
|
|
217
|
-
this.setSelectedRate(this.prevSelectedRate)
|
|
252
|
+
this.setSelectedRate(this.prevSelectedRate)
|
|
218
253
|
}
|
|
219
254
|
}
|
|
220
255
|
|
|
221
256
|
private onPlay() {
|
|
222
|
-
if (
|
|
223
|
-
this.
|
|
257
|
+
if (
|
|
258
|
+
this.core.getPlaybackType() === Playback.LIVE &&
|
|
259
|
+
!this.core.activePlayback.dvrEnabled
|
|
260
|
+
) {
|
|
261
|
+
this.resetPlaybackRate()
|
|
224
262
|
} else {
|
|
225
|
-
this.setSelectedRate(this.selectedRate)
|
|
263
|
+
this.setSelectedRate(this.selectedRate)
|
|
226
264
|
}
|
|
227
265
|
}
|
|
228
266
|
|
|
229
267
|
private resetPlaybackRate() {
|
|
230
|
-
this.setSelectedRate(DEFAULT_PLAYBACK_RATE)
|
|
268
|
+
this.setSelectedRate(DEFAULT_PLAYBACK_RATE)
|
|
231
269
|
}
|
|
232
270
|
|
|
233
|
-
private onStop() {
|
|
234
|
-
}
|
|
271
|
+
private onStop() {}
|
|
235
272
|
|
|
236
273
|
private onRateSelect(event: MouseEvent) {
|
|
237
|
-
event.stopPropagation()
|
|
238
|
-
const rate = (event.currentTarget as HTMLElement).dataset.rate
|
|
274
|
+
event.stopPropagation()
|
|
275
|
+
const rate = (event.currentTarget as HTMLElement).dataset.rate
|
|
239
276
|
if (rate) {
|
|
240
|
-
this.setSelectedRate(rate)
|
|
241
|
-
this.highlightCurrentRate()
|
|
277
|
+
this.setSelectedRate(rate)
|
|
278
|
+
this.highlightCurrentRate()
|
|
242
279
|
}
|
|
243
280
|
|
|
244
|
-
return false
|
|
281
|
+
return false
|
|
245
282
|
}
|
|
246
283
|
|
|
247
284
|
private onShowMenu() {
|
|
248
|
-
this.$el.html(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
285
|
+
this.$el.html(
|
|
286
|
+
PlaybackRate.listTemplate({
|
|
287
|
+
playbackRates: this.playbackRates,
|
|
288
|
+
arrowLeftIcon,
|
|
289
|
+
checkIcon,
|
|
290
|
+
i18n: this.core.i18n,
|
|
291
|
+
}),
|
|
292
|
+
)
|
|
293
|
+
;(this.core.getPlugin('bottom_gear') as BottomGear)?.setContent(this.el)
|
|
294
|
+
this.highlightCurrentRate()
|
|
255
295
|
}
|
|
256
296
|
|
|
257
297
|
private goBack() {
|
|
258
298
|
setTimeout(() => {
|
|
259
299
|
this.core.getPlugin('bottom_gear').refresh()
|
|
260
|
-
}, 0)
|
|
300
|
+
}, 0)
|
|
261
301
|
}
|
|
262
302
|
|
|
263
303
|
private setSelectedRate(rate: string) {
|
|
264
304
|
// Set <video playbackRate="..."
|
|
265
|
-
this.core.activePlayback?.setPlaybackRate(rate)
|
|
266
|
-
this.selectedRate = rate
|
|
305
|
+
this.core.activePlayback?.setPlaybackRate(rate)
|
|
306
|
+
this.selectedRate = rate
|
|
267
307
|
}
|
|
268
308
|
|
|
269
309
|
private getTitle() {
|
|
270
|
-
return
|
|
310
|
+
return (
|
|
311
|
+
this.playbackRates.find((r) => r.value === this.selectedRate)?.label ||
|
|
312
|
+
this.selectedRate
|
|
313
|
+
)
|
|
271
314
|
}
|
|
272
315
|
|
|
273
316
|
private highlightCurrentRate() {
|
|
274
|
-
this.allRateElements().removeClass('current')
|
|
275
|
-
this.allRateElements().find('a').removeClass('gcore-skin-active')
|
|
317
|
+
this.allRateElements().removeClass('current')
|
|
318
|
+
this.allRateElements().find('a').removeClass('gcore-skin-active')
|
|
276
319
|
|
|
277
|
-
const currentLevelElement = this.rateElement(this.selectedRate)
|
|
320
|
+
const currentLevelElement = this.rateElement(this.selectedRate)
|
|
278
321
|
|
|
279
|
-
currentLevelElement.addClass('current')
|
|
280
|
-
currentLevelElement.find('a').addClass('gcore-skin-active')
|
|
322
|
+
currentLevelElement.addClass('current')
|
|
323
|
+
currentLevelElement.find('a').addClass('gcore-skin-active')
|
|
281
324
|
}
|
|
282
325
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
+
import { PlaybackRate } from '../PlaybackRate'
|
|
3
|
+
import {
|
|
4
|
+
createMockCore,
|
|
5
|
+
createMockMediaControl,
|
|
6
|
+
createMockPlugin,
|
|
7
|
+
} from '../../../testUtils'
|
|
8
|
+
import { $ } from '@clappr/core'
|
|
9
|
+
import { Logger, LogTracer, setTracer } from '@gcorevideo/utils'
|
|
10
|
+
|
|
11
|
+
Logger.enable('*')
|
|
12
|
+
setTracer(new LogTracer('PlaybackRate.test'))
|
|
13
|
+
|
|
14
|
+
describe('PlaybackRate', () => {
|
|
15
|
+
let core: any
|
|
16
|
+
let bottomGear: any
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
core = createMockCore()
|
|
19
|
+
const mediaControl = createMockMediaControl(core)
|
|
20
|
+
bottomGear = createMockGearPlugin()
|
|
21
|
+
core.getPlugin.mockImplementation((name: string) => {
|
|
22
|
+
if (name === 'bottom_gear') {
|
|
23
|
+
return bottomGear
|
|
24
|
+
}
|
|
25
|
+
if (name === 'media_control') {
|
|
26
|
+
return mediaControl
|
|
27
|
+
}
|
|
28
|
+
return null
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
it('should render', () => {
|
|
32
|
+
const playbackRate = new PlaybackRate(core)
|
|
33
|
+
core.emit('core:ready')
|
|
34
|
+
core.activePlayback.getPlaybackType.mockReturnValue('live')
|
|
35
|
+
core.emit('core:active:container:changed')
|
|
36
|
+
core.activePlayback.dvrEnabled = true
|
|
37
|
+
core.activeContainer.emit('container:dvr', true)
|
|
38
|
+
expect(playbackRate.el.innerHTML).toMatchSnapshot()
|
|
39
|
+
expect(bottomGear.getElement).toHaveBeenCalledWith('rate')
|
|
40
|
+
expect(
|
|
41
|
+
bottomGear.$el
|
|
42
|
+
.find('[data-rate]')
|
|
43
|
+
.text()
|
|
44
|
+
.replace(/\/assets.*\.svg/g, '')
|
|
45
|
+
.replace(/\s+/g, ' ')
|
|
46
|
+
.trim(),
|
|
47
|
+
).toEqual('playback_rate 1x')
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
function createMockGearPlugin() {
|
|
52
|
+
const elements = {
|
|
53
|
+
nerd: $(document.createElement('li')).attr('data-nerd', 'nerd'),
|
|
54
|
+
quality: $(document.createElement('li')).attr('data-quality', 'quality'),
|
|
55
|
+
rate: $(document.createElement('li')).attr('data-rate', 'rate'),
|
|
56
|
+
}
|
|
57
|
+
const $el = $(document.createElement('ul'))
|
|
58
|
+
$el.append(elements.nerd, elements.quality, elements.rate)
|
|
59
|
+
const plugin = Object.assign(createMockPlugin(), {
|
|
60
|
+
setContent: vi.fn(),
|
|
61
|
+
getElement: vi.fn((name: string) => elements[name]),
|
|
62
|
+
$el,
|
|
63
|
+
})
|
|
64
|
+
return plugin
|
|
65
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`PlaybackRate > should render 1`] = `
|
|
4
|
+
"<button class="gplayer-lite-btn gcore-skin-text-color gear-option" id="playback-rate-button">
|
|
5
|
+
<span class="gear-option_speed-icon">/assets/icons/new/speed.svg</span>
|
|
6
|
+
<span class="gear-option_label">playback_rate</span>
|
|
7
|
+
<span class="gear-option_arrow-right-icon">/assets/icons/new/arrow-right.svg</span>
|
|
8
|
+
<span class="gear-option_value">1x</span>
|
|
9
|
+
</button>
|
|
10
|
+
"
|
|
11
|
+
`;
|