@gcorevideo/player 2.20.3 → 2.20.5
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/error-screen/error_screen.ejs +3 -1
- package/dist/core.js +436 -210
- package/dist/index.css +1223 -1223
- package/dist/index.js +580 -392
- package/dist/player.d.ts +10 -0
- package/dist/plugins/index.css +754 -754
- package/dist/plugins/index.js +122 -163
- package/docs/api/player.contextmenupluginsettings.label.md +3 -0
- package/docs/api/player.contextmenupluginsettings.md +8 -3
- package/docs/api/player.contextmenupluginsettings.preventshowcontextmenu.md +3 -0
- package/docs/api/player.contextmenupluginsettings.url.md +3 -0
- package/docs/api/player.md +6 -2
- package/docs/api/player.multicamera._constructor_.md +3 -0
- package/docs/api/player.multicamera.activebyid.md +3 -0
- package/docs/api/player.multicamera.attributes.md +3 -0
- package/docs/api/player.multicamera.bindevents.md +3 -0
- package/docs/api/player.multicamera.events.md +3 -0
- package/docs/api/player.multicamera.getcameraslist.md +3 -0
- package/docs/api/player.multicamera.getcurrentcamera.md +3 -0
- package/docs/api/player.multicamera.md +28 -1
- package/docs/api/player.multicamera.name.md +3 -0
- package/docs/api/player.multicamera.render.md +3 -0
- package/docs/api/player.multicamera.supportedversion.md +3 -0
- package/docs/api/player.multicamera.template.md +3 -0
- package/docs/api/player.multicamera.unbindevents.md +3 -0
- package/docs/api/player.multicamera.version.md +3 -0
- package/docs/api/player.volumefadeevents.md +7 -0
- package/docs/api/player.zeptoresult.md +1 -0
- package/lib/Player.d.ts +5 -3
- package/lib/Player.d.ts.map +1 -1
- package/lib/Player.js +32 -8
- package/lib/internal.types.d.ts +7 -7
- package/lib/internal.types.d.ts.map +1 -1
- package/lib/playback/BasePlayback.d.ts +11 -0
- package/lib/playback/BasePlayback.d.ts.map +1 -0
- package/lib/playback/BasePlayback.js +33 -0
- package/lib/playback/dash-playback/DashPlayback.d.ts +3 -2
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +7 -7
- package/lib/playback/hls-playback/HlsPlayback.d.ts +2 -2
- package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/playback/hls-playback/HlsPlayback.js +8 -5
- package/lib/playback/utils.d.ts +2 -0
- package/lib/playback/utils.d.ts.map +1 -0
- package/lib/playback/utils.js +1 -0
- package/lib/playback.types.d.ts +10 -3
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/playback.types.js +3 -3
- package/lib/plugins/context-menu/ContextMenu.d.ts +4 -0
- package/lib/plugins/context-menu/ContextMenu.d.ts.map +1 -1
- package/lib/plugins/context-menu/ContextMenu.js +1 -2
- package/lib/plugins/error-screen/ErrorScreen.d.ts +39 -24
- package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
- package/lib/plugins/error-screen/ErrorScreen.js +70 -136
- package/lib/plugins/media-control/MediaControl.d.ts +1 -1
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +7 -5
- package/lib/plugins/multi-camera/MultiCamera.d.ts +1 -0
- package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -1
- package/lib/plugins/multi-camera/MultiCamera.js +5 -5
- package/lib/plugins/poster/Poster.js +1 -1
- package/lib/plugins/seek-time/SeekTime.js +1 -1
- package/lib/plugins/share/Share.js +1 -1
- package/lib/plugins/source-controller/SourceController.d.ts +2 -1
- package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
- package/lib/plugins/source-controller/SourceController.js +12 -6
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +2 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +19 -3
- package/lib/plugins/volume-fade/VolumeFade.d.ts +4 -0
- package/lib/plugins/volume-fade/VolumeFade.d.ts.map +1 -1
- package/lib/plugins/volume-fade/VolumeFade.js +4 -0
- package/lib/testUtils.d.ts +66 -2
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +95 -2
- package/lib/types.d.ts +9 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/types.d.ts +1 -0
- package/lib/utils/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/release_notes +297 -0
- package/src/Player.ts +103 -48
- package/src/__tests__/Player.test.ts +25 -4
- package/src/internal.types.ts +86 -79
- package/src/playback/BasePlayback.ts +41 -0
- package/src/playback/dash-playback/DashPlayback.ts +11 -15
- package/src/playback/hls-playback/HlsPlayback.ts +7 -5
- package/src/playback/utils.ts +2 -0
- package/src/playback.types.ts +11 -3
- package/src/plugins/context-menu/ContextMenu.ts +5 -2
- package/src/plugins/error-screen/ErrorScreen.ts +121 -195
- package/src/plugins/error-screen/__tests__/ErrorScreen.test.ts +113 -0
- package/src/plugins/error-screen/__tests__/__snapshots__/ErrorScreen.test.ts.snap +20 -0
- package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +32 -57
- package/src/plugins/media-control/MediaControl.ts +8 -5
- package/src/plugins/multi-camera/MultiCamera.ts +5 -5
- package/src/plugins/poster/Poster.ts +1 -1
- package/src/plugins/seek-time/SeekTime.ts +1 -1
- package/src/plugins/share/Share.ts +1 -1
- package/src/plugins/source-controller/SourceController.ts +20 -14
- package/src/plugins/source-controller/__tests__/SourceController.test.ts +29 -46
- package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +20 -3
- package/src/plugins/volume-fade/VolumeFade.ts +4 -0
- package/src/testUtils.ts +100 -3
- package/src/types.ts +11 -1
- package/src/utils/types.ts +1 -0
- package/temp/player.api.json +24 -24
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,246 +1,172 @@
|
|
|
1
|
-
import { UICorePlugin, Events, template
|
|
2
|
-
import { trace } from '@gcorevideo/utils'
|
|
3
|
-
|
|
4
|
-
import { CLAPPR_VERSION } from '../../build.js'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import '
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { UICorePlugin, Events, template } from '@clappr/core'
|
|
2
|
+
import { trace } from '@gcorevideo/utils'
|
|
3
|
+
|
|
4
|
+
import { CLAPPR_VERSION } from '../../build.js'
|
|
5
|
+
|
|
6
|
+
import reloadIcon from '../../../assets/icons/old/reload.svg'
|
|
7
|
+
import templateHtml from '../../../assets/error-screen/error_screen.ejs'
|
|
8
|
+
import '../../../assets/error-screen/error_screen.scss'
|
|
9
|
+
import { PlaybackErrorCode } from '../../playback.types.js'
|
|
10
|
+
|
|
11
|
+
export type ErrorDesc = {
|
|
12
|
+
description: string
|
|
13
|
+
level: string
|
|
14
|
+
code: string
|
|
15
|
+
origin: string
|
|
16
|
+
scope: string
|
|
17
|
+
raw?: string
|
|
18
|
+
UI?: {
|
|
19
|
+
icon?: string
|
|
20
|
+
title: string
|
|
21
|
+
message: string
|
|
22
|
+
}
|
|
23
|
+
}
|
|
13
24
|
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
origin: string;
|
|
25
|
+
type ErrorScreenDesc = {
|
|
26
|
+
title: string
|
|
27
|
+
message: string
|
|
28
|
+
code: string
|
|
29
|
+
icon?: string
|
|
20
30
|
}
|
|
21
31
|
|
|
22
|
-
type
|
|
23
|
-
|
|
24
|
-
message: string;
|
|
25
|
-
code: string;
|
|
26
|
-
icon: string;
|
|
27
|
-
reloadIcon: string;
|
|
32
|
+
export type ErrorScreenPluginSettings = {
|
|
33
|
+
noReload?: boolean
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
const T = 'plugins.error_screen'
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
|
-
* Displays
|
|
39
|
+
* Displays an error nicely in the overlay on top of the player.
|
|
34
40
|
* @beta
|
|
35
41
|
*/
|
|
36
42
|
export class ErrorScreen extends UICorePlugin {
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
private err: PresentationalError | null = null;
|
|
40
|
-
|
|
41
|
-
private hideValue = false;
|
|
42
|
-
|
|
43
|
-
private timeout: TimerId | null = null;
|
|
44
|
-
|
|
45
|
-
private reloadButton: ZeptoResult | null = null;
|
|
43
|
+
private err: ErrorScreenDesc | null = null
|
|
46
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
47
48
|
get name() {
|
|
48
|
-
return '
|
|
49
|
+
return 'error_screen'
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
51
55
|
get supportedVersion() {
|
|
52
|
-
return { min: CLAPPR_VERSION }
|
|
56
|
+
return { min: CLAPPR_VERSION }
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
return template(templateHtml);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
get container() {
|
|
60
|
-
return this.core.activeContainer;
|
|
61
|
-
}
|
|
59
|
+
private static readonly template = template(templateHtml)
|
|
62
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
63
64
|
override get attributes() {
|
|
64
65
|
return {
|
|
65
|
-
|
|
66
|
+
class: 'player-error-screen',
|
|
66
67
|
'data-error-screen': '',
|
|
67
|
-
}
|
|
68
|
+
}
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
70
74
|
override bindEvents() {
|
|
71
|
-
this.listenTo(this.core, Events.ERROR, this.onError)
|
|
72
|
-
this.listenTo(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
private onCoreReady() {
|
|
79
|
-
trace(`${T} onCoreReady`)
|
|
80
|
-
if (this.core.activePlayback) {
|
|
81
|
-
this.listenTo(this.core.activePlayback, Events.PLAYBACK_PLAY, this.onPlay);
|
|
82
|
-
}
|
|
75
|
+
this.listenTo(this.core, Events.ERROR, this.onError)
|
|
76
|
+
this.listenTo(
|
|
77
|
+
this.core,
|
|
78
|
+
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
79
|
+
this.onActiveContainerChanged,
|
|
80
|
+
)
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
private onPlay() {
|
|
86
84
|
trace(`${T} onPlay`)
|
|
87
|
-
this.
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private destroyError() {
|
|
91
|
-
trace(`${T} destroyError`)
|
|
92
|
-
this._retry = 0;
|
|
93
|
-
this.err = null;
|
|
94
|
-
if (this.timeout !== null) {
|
|
95
|
-
clearTimeout(this.timeout);
|
|
96
|
-
this.timeout = null;
|
|
97
|
-
}
|
|
98
|
-
this.$el.hide();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
unBindEvents() {
|
|
102
|
-
// @ts-ignore
|
|
103
|
-
this.stopListening(this.core, 'core:advertisement:start');
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
this.stopListening(this.core, 'core:advertisement:finish');
|
|
106
|
-
// @ts-ignore
|
|
107
|
-
this.stopListening(this.core, Events.ERROR);
|
|
85
|
+
this.unmount()
|
|
108
86
|
}
|
|
109
87
|
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
this.
|
|
88
|
+
private unmount() {
|
|
89
|
+
trace(`${T} unmount`)
|
|
90
|
+
this.err = null
|
|
91
|
+
this.$el.empty()
|
|
92
|
+
// this.$el.hide();
|
|
113
93
|
}
|
|
114
94
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.core.activeContainer.mediaControlDisabled = false;
|
|
122
|
-
this.unbindReload();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private unbindReload() {
|
|
126
|
-
this.reloadButton && this.reloadButton.off('click');
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private onContainerChanged() {
|
|
130
|
-
this.err = null;
|
|
131
|
-
if (this.core.getPlugin('error_screen')) {
|
|
132
|
-
this.core.getPlugin('error_screen').disable();
|
|
133
|
-
}
|
|
134
|
-
this.unbindReload();
|
|
135
|
-
this.hide();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
private onStartAd() {
|
|
139
|
-
this.hideValue = true;
|
|
140
|
-
if (this.err) {
|
|
141
|
-
this.hide();
|
|
95
|
+
/**
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
override get events() {
|
|
99
|
+
return {
|
|
100
|
+
'click .player-error-screen__reload': 'reload',
|
|
142
101
|
}
|
|
143
102
|
}
|
|
144
103
|
|
|
145
|
-
private
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
104
|
+
private reload() {
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
this.core.configure({
|
|
107
|
+
reloading: true,
|
|
108
|
+
source: this.core.options.source,
|
|
109
|
+
sources: this.core.options.sources,
|
|
110
|
+
})
|
|
111
|
+
}, 0)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private onActiveContainerChanged() {
|
|
115
|
+
trace(`${T} onActiveContainerChanged`, {
|
|
116
|
+
reloading: this.core.options.reloading,
|
|
117
|
+
})
|
|
118
|
+
this.err = null
|
|
119
|
+
this.listenTo(
|
|
120
|
+
this.core.activeContainer.playback,
|
|
121
|
+
Events.PLAYBACK_PLAY,
|
|
122
|
+
this.onPlay,
|
|
123
|
+
)
|
|
124
|
+
if (this.core.options.reloading) {
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
this.core.options.reloading = false
|
|
127
|
+
this.unmount()
|
|
128
|
+
this.core.activeContainer.play({
|
|
129
|
+
reloading: true,
|
|
130
|
+
})
|
|
131
|
+
}, 0)
|
|
151
132
|
}
|
|
152
133
|
}
|
|
153
134
|
|
|
154
|
-
private onError(err:
|
|
135
|
+
private onError(err: ErrorDesc) {
|
|
155
136
|
trace(`${T} onError`, { err })
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
err.details === 'manifestParsingError'
|
|
160
|
-
) {
|
|
161
|
-
this.err = {
|
|
162
|
-
title: this.core.i18n.t('no_broadcast'),
|
|
163
|
-
message: '',
|
|
164
|
-
code: '',
|
|
165
|
-
// icon: (this.err.UI && this.err.UI.icon) || '',
|
|
166
|
-
icon: '',
|
|
167
|
-
reloadIcon,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
if (this.options.errorScreen?.reloadOnError === false) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (this.options.errorScreen?.neverStopToRetry) {
|
|
175
|
-
this._retry = 0;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (this._retry >= MAX_RETRY) {
|
|
179
|
-
this.drying();
|
|
180
|
-
|
|
181
|
-
return;
|
|
137
|
+
if (err.UI) {
|
|
138
|
+
if (this.err) {
|
|
139
|
+
this.unmount()
|
|
182
140
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// clickToPausePlugin.afterEnabled = true;
|
|
189
|
-
ctp.disable();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
this.timeout = setTimeout(() => {
|
|
193
|
-
if (toggleCTP) {
|
|
194
|
-
ctp.enable();
|
|
195
|
-
}
|
|
196
|
-
this.reload();
|
|
197
|
-
}, TIME_FOR_UPDATE);
|
|
198
|
-
|
|
199
|
-
const spinnerPlugin = this.container.getPlugin('spinner');
|
|
200
|
-
if (spinnerPlugin) {
|
|
201
|
-
spinnerPlugin.show(); // TODO remove?
|
|
202
|
-
setTimeout(() => spinnerPlugin.show(), 0);
|
|
141
|
+
this.err = {
|
|
142
|
+
title: err.UI.title,
|
|
143
|
+
message: err.UI.message,
|
|
144
|
+
code: err.code,
|
|
145
|
+
icon: err.UI.icon,
|
|
203
146
|
}
|
|
147
|
+
this.render()
|
|
204
148
|
}
|
|
205
149
|
}
|
|
206
150
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
spinnerPlugin?.hide();
|
|
211
|
-
|
|
212
|
-
this._retry = 0;
|
|
213
|
-
if (!this.hideValue) {
|
|
214
|
-
this.container.disableMediaControl();
|
|
215
|
-
this.container.stop();
|
|
216
|
-
this.show();
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
show(err?: PresentationalError) {
|
|
221
|
-
if (err) {
|
|
222
|
-
this.err = err;
|
|
223
|
-
}
|
|
224
|
-
// TODO use container.disableMediaControl() instead
|
|
225
|
-
this.core.mediaControl.disable();
|
|
226
|
-
this.render();
|
|
227
|
-
this.$el.show();
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
hide() {
|
|
231
|
-
this.$el.hide();
|
|
232
|
-
}
|
|
233
|
-
|
|
151
|
+
/**
|
|
152
|
+
* @internal
|
|
153
|
+
*/
|
|
234
154
|
override render() {
|
|
235
155
|
if (!this.err) {
|
|
236
|
-
return this
|
|
156
|
+
return this
|
|
157
|
+
}
|
|
158
|
+
this.$el.html(
|
|
159
|
+
ErrorScreen.template({
|
|
160
|
+
...this.err,
|
|
161
|
+
reloadIcon: this.options.errorScreen?.noReload ? null : reloadIcon,
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
// TODO append to container instead of core?
|
|
166
|
+
if (!this.el.parentElement) {
|
|
167
|
+
this.core.$el.append(this.el)
|
|
237
168
|
}
|
|
238
|
-
this.$el.html(this.template(this.err));
|
|
239
|
-
|
|
240
|
-
this.core.$el.append(this.el);
|
|
241
|
-
|
|
242
|
-
this.bindReload();
|
|
243
169
|
|
|
244
|
-
return this
|
|
170
|
+
return this
|
|
245
171
|
}
|
|
246
172
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { createMockContainer, createMockCore, createMockPlayback } from '../../../testUtils'
|
|
2
|
+
import { ErrorScreen } from '../ErrorScreen'
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
|
+
|
|
5
|
+
describe('ErrorScreen', () => {
|
|
6
|
+
let core: any
|
|
7
|
+
let container: any
|
|
8
|
+
let playback: any
|
|
9
|
+
let errorScreen: ErrorScreen
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
core = createMockCore()
|
|
12
|
+
container = createMockContainer()
|
|
13
|
+
playback = createMockPlayback()
|
|
14
|
+
container.playback = playback
|
|
15
|
+
core.activeContainer = container
|
|
16
|
+
})
|
|
17
|
+
describe('on error', () => {
|
|
18
|
+
describe.each([
|
|
19
|
+
[
|
|
20
|
+
'targeted at UI',
|
|
21
|
+
{
|
|
22
|
+
code: "foo",
|
|
23
|
+
UI: {
|
|
24
|
+
title: 'My error',
|
|
25
|
+
message: 'Lorem ipsum dolor sit amet',
|
|
26
|
+
icon: '<svg>...</svg>'
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
true,
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
'other',
|
|
33
|
+
{
|
|
34
|
+
code: 'MEDIA_SOURCE_ACCESS_DENIED',
|
|
35
|
+
title: 'The server refused to serve the protected media',
|
|
36
|
+
message: 'Wrong credentials',
|
|
37
|
+
},
|
|
38
|
+
false,
|
|
39
|
+
],
|
|
40
|
+
])("%s", (_, err, shouldRender) => {
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
errorScreen = new ErrorScreen(core)
|
|
43
|
+
core.emit('core:ready')
|
|
44
|
+
core.emit('core:active:container:changed')
|
|
45
|
+
core.emit('error', err)
|
|
46
|
+
})
|
|
47
|
+
if (shouldRender) {
|
|
48
|
+
it('should render', () => {
|
|
49
|
+
expect(errorScreen.el.innerHTML).toBeTruthy()
|
|
50
|
+
expect(errorScreen.el.innerHTML).toMatchSnapshot()
|
|
51
|
+
})
|
|
52
|
+
} else {
|
|
53
|
+
it('should not render', () => {
|
|
54
|
+
expect(errorScreen.el.innerHTML).toBeFalsy()
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
describe('reload button', () => {
|
|
59
|
+
describe('basically', () => {
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
core.options.source = 'https://222/master.mpd'
|
|
62
|
+
errorScreen = new ErrorScreen(core)
|
|
63
|
+
core.emit('core:ready')
|
|
64
|
+
core.emit('core:active:container:changed')
|
|
65
|
+
core.emit('error', {
|
|
66
|
+
code: 'foo',
|
|
67
|
+
UI: {
|
|
68
|
+
title: 'My error',
|
|
69
|
+
message: 'Lorem ipsum dolor sit amet',
|
|
70
|
+
icon: '<svg>...</svg>'
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
core.configure.mockClear()
|
|
74
|
+
})
|
|
75
|
+
describe('when clicked', () => {
|
|
76
|
+
beforeEach(async () => {
|
|
77
|
+
(errorScreen.el.querySelector('.player-error-screen__reload') as HTMLElement)?.click()
|
|
78
|
+
return new Promise(resolve => setTimeout(resolve, 0))
|
|
79
|
+
})
|
|
80
|
+
it('should reload the player', () => {
|
|
81
|
+
expect(core.configure).toHaveBeenCalledWith(expect.objectContaining({
|
|
82
|
+
reloading: true,
|
|
83
|
+
source: 'https://222/master.mpd'
|
|
84
|
+
}))
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
describe('when disabled', () => {
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
core.options.errorScreen = {
|
|
91
|
+
noReload: true
|
|
92
|
+
}
|
|
93
|
+
errorScreen = new ErrorScreen(core)
|
|
94
|
+
core.emit('core:ready')
|
|
95
|
+
core.emit('core:active:container:changed')
|
|
96
|
+
core.emit('error', {
|
|
97
|
+
code: 'foo',
|
|
98
|
+
UI: {
|
|
99
|
+
title: 'My error',
|
|
100
|
+
message: 'Lorem ipsum dolor sit amet',
|
|
101
|
+
icon: '<svg>...</svg>'
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
it('should not render the reload button', () => {
|
|
106
|
+
expect(errorScreen.el.querySelector('.player-error-screen__reload')).toBeNull()
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`ErrorScreen > on error > targeted at UI > should render 1`] = `
|
|
4
|
+
"<div class="player-error-screen__content" data-error-screen="">
|
|
5
|
+
|
|
6
|
+
<div class="player-error-screen__icon" data-error-screen=""><svg>...</svg></div>
|
|
7
|
+
|
|
8
|
+
<div class="player-error-screen__title" data-error-screen="">My error</div>
|
|
9
|
+
|
|
10
|
+
<div class="player-error-screen__message" data-error-screen="">Lorem ipsum dolor sit amet</div>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<div class="player-error-screen__code" data-error-screen="">Error code: foo</div>
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<div class="player-error-screen__reload" data-error-screen="">/assets/icons/old/reload.svg</div>
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
"
|
|
20
|
+
`;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
2
|
import { UICorePlugin } from '@clappr/core'
|
|
3
3
|
import FakeTimers from '@sinonjs/fake-timers'
|
|
4
|
-
import EventLite from 'event-lite'
|
|
5
4
|
import { Logger, LogTracer, setTracer } from '@gcorevideo/utils'
|
|
6
5
|
import { LevelSelector } from '../LevelSelector.js'
|
|
6
|
+
import { createMockCore, createMockPlayback } from '../../../testUtils.js'
|
|
7
7
|
|
|
8
8
|
setTracer(new LogTracer('LevelSelector.test'))
|
|
9
9
|
Logger.enable('*')
|
|
@@ -41,28 +41,25 @@ describe('LevelSelector', () => {
|
|
|
41
41
|
})
|
|
42
42
|
describe('basically', () => {
|
|
43
43
|
beforeEach(() => {
|
|
44
|
-
const activeContainer =
|
|
45
|
-
activePlayback = createPlayback()
|
|
44
|
+
// const activeContainer = createMockContainer()
|
|
46
45
|
let mediaControl: UICorePlugin | null = null
|
|
47
46
|
let bottomGear: UICorePlugin | null = null
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// restrictResolution: 360,
|
|
54
|
-
labels: { 360: '360p', 720: 'HD' },
|
|
55
|
-
},
|
|
47
|
+
// TODO create mock core
|
|
48
|
+
core = createMockCore({
|
|
49
|
+
levelSelector: {
|
|
50
|
+
// restrictResolution: 360,
|
|
51
|
+
labels: { 360: '360p', 720: 'HD' },
|
|
56
52
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
65
|
-
}
|
|
53
|
+
})
|
|
54
|
+
activePlayback = core.activePlayback
|
|
55
|
+
core.getPlugin.mockImplementation((name: string) => {
|
|
56
|
+
if (name === 'media_control') {
|
|
57
|
+
return mediaControl
|
|
58
|
+
}
|
|
59
|
+
if (name === 'bottom_gear') {
|
|
60
|
+
return bottomGear
|
|
61
|
+
}
|
|
62
|
+
return null
|
|
66
63
|
})
|
|
67
64
|
mediaControl = createMediaControl(core)
|
|
68
65
|
bottomGear = createBottomGear(core)
|
|
@@ -75,7 +72,7 @@ describe('LevelSelector', () => {
|
|
|
75
72
|
activePlayback.emit('playback:levels:available', LEVELS)
|
|
76
73
|
await clock.tickAsync(1)
|
|
77
74
|
})
|
|
78
|
-
it('should render
|
|
75
|
+
it('should render proper level label', () => {
|
|
79
76
|
// @ts-ignore
|
|
80
77
|
expect(levelSelector.el.textContent).toMatchQualityLevelLabel('Auto')
|
|
81
78
|
})
|
|
@@ -111,28 +108,23 @@ describe('LevelSelector', () => {
|
|
|
111
108
|
})
|
|
112
109
|
describe('options.restrictResolution', () => {
|
|
113
110
|
beforeEach(() => {
|
|
114
|
-
const activeContainer = createContainer()
|
|
115
|
-
activePlayback = createPlayback()
|
|
116
111
|
let mediaControl: UICorePlugin | null = null
|
|
117
112
|
let bottomGear: UICorePlugin | null = null
|
|
118
|
-
core =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
levelSelector: {
|
|
123
|
-
restrictResolution: 360,
|
|
124
|
-
labels: { 360: '360p', 720: '720p' },
|
|
125
|
-
},
|
|
113
|
+
core = createMockCore({
|
|
114
|
+
levelSelector: {
|
|
115
|
+
restrictResolution: 360,
|
|
116
|
+
labels: { 360: '360p', 720: '720p' },
|
|
126
117
|
},
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return
|
|
135
|
-
}
|
|
118
|
+
})
|
|
119
|
+
activePlayback = core.activePlayback
|
|
120
|
+
core.getPlugin.mockImplementation((name: string) => {
|
|
121
|
+
if (name === 'media_control') {
|
|
122
|
+
return mediaControl
|
|
123
|
+
}
|
|
124
|
+
if (name === 'bottom_gear') {
|
|
125
|
+
return bottomGear
|
|
126
|
+
}
|
|
127
|
+
return null
|
|
136
128
|
})
|
|
137
129
|
mediaControl = createMediaControl(core)
|
|
138
130
|
bottomGear = createBottomGear(core)
|
|
@@ -196,23 +188,6 @@ describe('LevelSelector', () => {
|
|
|
196
188
|
})
|
|
197
189
|
})
|
|
198
190
|
|
|
199
|
-
function createContainer() {
|
|
200
|
-
const container = Object.assign(new EventLite(), {
|
|
201
|
-
$el: {
|
|
202
|
-
html: vi.fn(),
|
|
203
|
-
},
|
|
204
|
-
})
|
|
205
|
-
return container
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function createPlayback() {
|
|
209
|
-
const playback = Object.assign(new EventLite(), {
|
|
210
|
-
currentLevel: -1,
|
|
211
|
-
levels: [],
|
|
212
|
-
})
|
|
213
|
-
return playback
|
|
214
|
-
}
|
|
215
|
-
|
|
216
191
|
expect.extend({
|
|
217
192
|
toMatchQualityLevelLabel(received, expected) {
|
|
218
193
|
const { isNot } = this
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
$,
|
|
14
14
|
Core,
|
|
15
15
|
} from '@clappr/core'
|
|
16
|
-
import { reportError } from '@gcorevideo/utils'
|
|
16
|
+
import { reportError, trace } from '@gcorevideo/utils'
|
|
17
|
+
|
|
17
18
|
import { type TimeProgress } from '../../playback.types.js'
|
|
18
19
|
|
|
19
20
|
import { Kibo } from '../kibo/index.js'
|
|
@@ -417,9 +418,10 @@ export class MediaControl extends UICorePlugin {
|
|
|
417
418
|
}
|
|
418
419
|
|
|
419
420
|
/**
|
|
420
|
-
*
|
|
421
|
+
* Hides the media control UI
|
|
421
422
|
*/
|
|
422
423
|
override disable() {
|
|
424
|
+
trace(`${T} disable`)
|
|
423
425
|
this.userDisabled = true
|
|
424
426
|
this.hide()
|
|
425
427
|
this.unbindKeyEvents()
|
|
@@ -430,6 +432,7 @@ export class MediaControl extends UICorePlugin {
|
|
|
430
432
|
* Reenables the plugin disabled earlier with the {@link MediaControl.disable} method
|
|
431
433
|
*/
|
|
432
434
|
override enable() {
|
|
435
|
+
trace(`${T} enable`)
|
|
433
436
|
if (this.options.chromeless) {
|
|
434
437
|
return
|
|
435
438
|
}
|
|
@@ -1273,14 +1276,14 @@ export class MediaControl extends UICorePlugin {
|
|
|
1273
1276
|
override destroy() {
|
|
1274
1277
|
$(document).unbind('mouseup', this.stopDrag)
|
|
1275
1278
|
$(document).unbind('mousemove', this.updateDrag)
|
|
1279
|
+
$(document).unbind('touchend', this.stopDrag)
|
|
1280
|
+
$(document).unbind('touchmove', this.updateDrag)
|
|
1276
1281
|
this.unbindKeyEvents()
|
|
1277
|
-
// @ts-ignore
|
|
1278
|
-
this.stopListening()
|
|
1279
1282
|
return super.destroy()
|
|
1280
1283
|
}
|
|
1281
1284
|
|
|
1282
1285
|
private configure() {
|
|
1283
|
-
this.advertisementPlaying ? this.disable() : this.enable()
|
|
1286
|
+
// this.advertisementPlaying ? this.disable() : this.enable()
|
|
1284
1287
|
this.trigger(Events.MEDIACONTROL_OPTIONS_CHANGE)
|
|
1285
1288
|
}
|
|
1286
1289
|
|