@gcorevideo/player 2.20.9 → 2.20.12
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/dvr-controls/dvr_controls.scss +0 -2
- package/dist/core.js +5 -5
- package/dist/index.css +1521 -1524
- package/dist/index.js +101 -106
- package/dist/player.d.ts +141 -100
- package/dist/plugins/index.css +1376 -1379
- package/dist/plugins/index.js +96 -102
- package/docs/api/player.audioselector.md +1 -1
- package/docs/api/player.bigmutebutton.md +1 -1
- package/docs/api/player.bottomgear.md +1 -1
- package/docs/api/player.clapprnerdstats.md +1 -1
- package/docs/api/player.clapprstats.md +1 -1
- package/docs/api/player.clicktopause.md +1 -1
- package/docs/api/player.clipsplugin.md +1 -1
- package/docs/api/player.containerpluginconstructor.md +3 -5
- package/docs/api/player.containersize.md +0 -3
- package/docs/api/player.contextmenu.md +1 -1
- package/docs/api/player.contextmenupluginsettings.md +1 -1
- package/docs/api/player.corepluginconstructor.md +3 -5
- package/docs/api/player.dashsettings.md +0 -3
- package/docs/api/player.dvrcontrols.md +2 -35
- package/docs/api/player.errorlevel.md +0 -3
- package/docs/api/player.errorscreen.md +1 -1
- package/docs/api/player.favicon.md +4 -174
- package/docs/api/{player.favicon.disable.md → player.faviconpluginsettings.faviconcolor.md} +5 -7
- package/docs/api/{player.dvrcontrols._constructor_.md → player.faviconpluginsettings.md} +17 -8
- package/docs/api/player.googleanalytics.md +1 -1
- package/docs/api/player.langtag.md +0 -3
- package/docs/api/player.levelselector.md +1 -1
- package/docs/api/player.logo.md +1 -1
- package/docs/api/player.md +82 -82
- package/docs/api/{player.favicon.configure.md → player.mediacontrol.getcenterpanel.md} +4 -4
- package/docs/api/{player.favicon.destroy.md → player.mediacontrol.getleftpanel.md} +8 -4
- package/docs/api/player.mediacontrol.md +30 -2
- package/docs/api/player.multicamera.md +1 -1
- package/docs/api/player.pictureinpicture.md +1 -1
- package/docs/api/player.playbackerror.code.md +0 -3
- package/docs/api/player.playbackerror.description.md +0 -3
- package/docs/api/player.playbackerror.level.md +0 -3
- package/docs/api/player.playbackerror.md +8 -11
- package/docs/api/player.playbackerror.message.md +0 -3
- package/docs/api/player.playbackerror.origin.md +0 -3
- package/docs/api/player.playbackerror.scope.md +0 -3
- package/docs/api/player.playbackerror.ui.md +1 -3
- package/docs/api/player.playbackerrorcode.md +3 -6
- package/docs/api/player.playbackmodule.md +0 -3
- package/docs/api/player.playbackrate.md +1 -1
- package/docs/api/player.playbacktype.md +1 -4
- package/docs/api/player.player._constructor_.md +0 -3
- package/docs/api/player.player.attachto.md +0 -3
- package/docs/api/player.player.configure.md +0 -3
- package/docs/api/player.player.destroy.md +0 -3
- package/docs/api/player.player.getcurrenttime.md +0 -3
- package/docs/api/player.player.getduration.md +0 -3
- package/docs/api/player.player.getvolume.md +0 -3
- package/docs/api/player.player.isdvrenabled.md +0 -3
- package/docs/api/player.player.isdvrinuse.md +0 -3
- package/docs/api/player.player.ismuted.md +0 -3
- package/docs/api/player.player.isplaying.md +0 -3
- package/docs/api/player.player.md +25 -28
- package/docs/api/player.player.mute.md +0 -3
- package/docs/api/player.player.off.md +0 -3
- package/docs/api/player.player.on.md +0 -3
- package/docs/api/player.player.pause.md +0 -3
- package/docs/api/player.player.play.md +0 -3
- package/docs/api/player.player.registerplugin.md +0 -3
- package/docs/api/player.player.resize.md +0 -3
- package/docs/api/player.player.seek.md +0 -3
- package/docs/api/player.player.setvolume.md +0 -3
- package/docs/api/player.player.stop.md +0 -3
- package/docs/api/player.player.unmute.md +0 -3
- package/docs/api/player.player.unregisterplugin.md +14 -7
- package/docs/api/player.playercomponenttype.md +0 -3
- package/docs/api/player.playerconfig.autoplay.md +0 -3
- package/docs/api/player.playerconfig.dash.md +0 -3
- package/docs/api/player.playerconfig.debug.md +0 -3
- package/docs/api/player.playerconfig.language.md +0 -3
- package/docs/api/player.playerconfig.loop.md +0 -3
- package/docs/api/player.playerconfig.md +10 -13
- package/docs/api/player.playerconfig.mute.md +0 -3
- package/docs/api/player.playerconfig.playbacktype.md +0 -3
- package/docs/api/player.playerconfig.prioritytransport.md +0 -3
- package/docs/api/player.playerconfig.sources.md +0 -3
- package/docs/api/player.playerconfig.strings.md +0 -3
- package/docs/api/player.playerdebugsettings.md +0 -3
- package/docs/api/player.playerdebugtag.md +0 -3
- package/docs/api/player.playerevent.md +11 -14
- package/docs/api/player.playereventhandler.md +0 -3
- package/docs/api/player.playereventparams.md +0 -3
- package/docs/api/player.playermediasource.md +0 -3
- package/docs/api/player.playermediasourcedesc.md +2 -5
- package/docs/api/player.playermediasourcedesc.mimetype.md +0 -3
- package/docs/api/player.playermediasourcedesc.source.md +0 -3
- package/docs/api/player.playerplugin.md +0 -4
- package/docs/api/player.playerpluginconstructor.md +0 -3
- package/docs/api/player.poster.md +1 -1
- package/docs/api/player.qualitylevel.bitrate.md +0 -3
- package/docs/api/player.qualitylevel.height.md +0 -3
- package/docs/api/player.qualitylevel.level.md +0 -3
- package/docs/api/player.qualitylevel.md +4 -7
- package/docs/api/player.qualitylevel.width.md +0 -3
- package/docs/api/player.seektime.md +1 -1
- package/docs/api/player.share.md +1 -1
- package/docs/api/player.skiptime.md +1 -1
- package/docs/api/player.sourcecontroller.md +1 -1
- package/docs/api/player.spinnerthreebounce.md +1 -1
- package/docs/api/player.subtitles.md +1 -1
- package/docs/api/player.telemetry.md +1 -1
- package/docs/api/player.thumbnails.md +1 -1
- package/docs/api/player.timeposition.current.md +0 -3
- package/docs/api/player.timeposition.md +2 -5
- package/docs/api/player.timeposition.total.md +0 -3
- package/docs/api/player.timevalue.md +0 -3
- package/docs/api/player.translationkey.md +0 -3
- package/docs/api/player.translationsettings.md +0 -3
- package/docs/api/player.transportpreference.md +2 -7
- package/docs/api/player.volumefade.md +1 -1
- package/lib/Player.d.ts +5 -5
- package/lib/Player.js +2 -2
- package/lib/index.d.ts +18 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +18 -1
- package/lib/playback.types.d.ts +8 -7
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/playback.types.js +1 -1
- package/lib/plugins/audio-selector/AudioSelector.d.ts +1 -1
- package/lib/plugins/audio-selector/AudioSelector.js +1 -1
- package/lib/plugins/big-mute-button/BigMuteButton.d.ts +1 -1
- package/lib/plugins/big-mute-button/BigMuteButton.d.ts.map +1 -1
- package/lib/plugins/big-mute-button/BigMuteButton.js +1 -2
- package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +1 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +1 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +1 -1
- package/lib/plugins/clappr-stats/ClapprStats.d.ts +1 -1
- package/lib/plugins/clappr-stats/ClapprStats.js +1 -1
- package/lib/plugins/click-to-pause/ClickToPause.d.ts +1 -1
- package/lib/plugins/click-to-pause/ClickToPause.js +1 -1
- package/lib/plugins/clips/Clips.d.ts +1 -1
- package/lib/plugins/clips/Clips.js +1 -1
- package/lib/plugins/context-menu/ContextMenu.d.ts +2 -2
- package/lib/plugins/context-menu/ContextMenu.js +1 -1
- package/lib/plugins/dvr-controls/DvrControls.d.ts +6 -4
- package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
- package/lib/plugins/dvr-controls/DvrControls.js +28 -36
- package/lib/plugins/error-screen/ErrorScreen.d.ts +1 -18
- package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
- package/lib/plugins/error-screen/ErrorScreen.js +1 -2
- package/lib/plugins/favicon/Favicon.d.ts +30 -3
- package/lib/plugins/favicon/Favicon.d.ts.map +1 -1
- package/lib/plugins/favicon/Favicon.js +28 -35
- package/lib/plugins/google-analytics/GoogleAnalytics.d.ts +1 -1
- package/lib/plugins/google-analytics/GoogleAnalytics.js +1 -1
- package/lib/plugins/level-selector/LevelSelector.d.ts +1 -1
- package/lib/plugins/level-selector/LevelSelector.js +1 -1
- package/lib/plugins/logo/Logo.d.ts +1 -1
- package/lib/plugins/logo/Logo.js +1 -1
- package/lib/plugins/media-control/MediaControl.d.ts +8 -2
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +15 -3
- package/lib/plugins/multi-camera/MultiCamera.d.ts +1 -1
- package/lib/plugins/multi-camera/MultiCamera.js +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -1
- package/lib/plugins/playback-rate/PlaybackRate.js +1 -1
- package/lib/plugins/poster/Poster.d.ts +1 -1
- package/lib/plugins/poster/Poster.js +1 -1
- package/lib/plugins/seek-time/SeekTime.d.ts +1 -1
- package/lib/plugins/seek-time/SeekTime.js +1 -1
- package/lib/plugins/share/Share.d.ts +1 -1
- package/lib/plugins/share/Share.js +1 -1
- package/lib/plugins/skip-time/SkipTime.d.ts +1 -1
- package/lib/plugins/skip-time/SkipTime.js +1 -1
- package/lib/plugins/source-controller/SourceController.d.ts +1 -1
- package/lib/plugins/source-controller/SourceController.js +1 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +1 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -1
- package/lib/plugins/subtitles/Subtitles.d.ts +1 -1
- package/lib/plugins/subtitles/Subtitles.js +1 -1
- package/lib/plugins/telemetry/Telemetry.d.ts +1 -1
- package/lib/plugins/telemetry/Telemetry.js +1 -1
- package/lib/plugins/thumbnails/Thumbnails.d.ts +1 -1
- package/lib/plugins/thumbnails/Thumbnails.js +1 -1
- package/lib/plugins/volume-fade/VolumeFade.d.ts +1 -1
- package/lib/plugins/volume-fade/VolumeFade.js +1 -1
- package/lib/testUtils.d.ts +11 -2
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +22 -3
- package/lib/types.d.ts +20 -25
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/package.json +1 -1
- package/src/Player.ts +5 -5
- package/src/index.ts +18 -1
- package/src/playback.types.ts +8 -7
- package/src/plugins/audio-selector/AudioSelector.ts +1 -1
- package/src/plugins/big-mute-button/BigMuteButton.ts +1 -2
- package/src/plugins/bottom-gear/BottomGear.ts +1 -1
- package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +1 -1
- package/src/plugins/clappr-stats/ClapprStats.ts +1 -1
- package/src/plugins/click-to-pause/ClickToPause.ts +1 -1
- package/src/plugins/clips/Clips.ts +1 -1
- package/src/plugins/context-menu/ContextMenu.ts +2 -2
- package/src/plugins/dvr-controls/DvrControls.ts +33 -45
- package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +91 -0
- package/src/plugins/dvr-controls/__tests__/__snapshots__/DvrControls.test.ts.snap +43 -0
- package/src/plugins/error-screen/ErrorScreen.ts +3 -22
- package/src/plugins/favicon/Favicon.ts +38 -41
- package/src/plugins/google-analytics/GoogleAnalytics.ts +1 -1
- package/src/plugins/level-selector/LevelSelector.ts +1 -1
- package/src/plugins/logo/Logo.ts +1 -1
- package/src/plugins/media-control/MediaControl.ts +17 -3
- package/src/plugins/multi-camera/MultiCamera.ts +1 -1
- package/src/plugins/picture-in-picture/PictureInPicture.ts +1 -1
- package/src/plugins/playback-rate/PlaybackRate.ts +1 -1
- 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/skip-time/SkipTime.ts +1 -1
- package/src/plugins/source-controller/SourceController.ts +1 -1
- package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -1
- package/src/plugins/subtitles/Subtitles.ts +1 -1
- package/src/plugins/telemetry/Telemetry.ts +1 -1
- package/src/plugins/thumbnails/Thumbnails.ts +1 -1
- package/src/plugins/volume-fade/VolumeFade.ts +1 -1
- package/src/testUtils.ts +28 -4
- package/src/types.ts +20 -26
- package/temp/player.api.json +274 -455
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.errordesc.md +0 -28
- package/docs/api/player.favicon._constructor_.md +0 -50
- package/docs/api/player.favicon.bindevents.md +0 -18
- package/docs/api/player.favicon.name.md +0 -14
- package/docs/api/player.favicon.supportedversion.md +0 -16
- package/docs/api/player.mediatransport.md +0 -16
|
@@ -6,11 +6,12 @@ import { CLAPPR_VERSION } from '../../build.js'
|
|
|
6
6
|
import dvrHTML from '../../../assets/dvr-controls/index.ejs'
|
|
7
7
|
import '../../../assets/dvr-controls/dvr_controls.scss'
|
|
8
8
|
import { trace } from '@gcorevideo/utils'
|
|
9
|
+
import { MediaControl } from '../media-control/MediaControl.js'
|
|
9
10
|
|
|
10
11
|
const T = 'plugins.dvr_controls'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* PLUGIN that adds the DVR controls to the media control UI
|
|
14
|
+
* `PLUGIN` that adds the DVR controls to the media control UI
|
|
14
15
|
*
|
|
15
16
|
* @beta
|
|
16
17
|
*
|
|
@@ -19,7 +20,9 @@ const T = 'plugins.dvr_controls'
|
|
|
19
20
|
*
|
|
20
21
|
* - {@link MediaControl}
|
|
21
22
|
*
|
|
22
|
-
* The plugin renders live stream indicator
|
|
23
|
+
* The plugin renders live stream indicator.
|
|
24
|
+
* If DVR is enabled, the indicator shows whether the current position is at the live edge of the stream or not.
|
|
25
|
+
* In the latter case, the indicator can be clicked to seek to the live edge.
|
|
23
26
|
*/
|
|
24
27
|
export class DvrControls extends UICorePlugin {
|
|
25
28
|
private static readonly template = template(dvrHTML)
|
|
@@ -57,15 +60,20 @@ export class DvrControls extends UICorePlugin {
|
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
constructor(core: Core) {
|
|
61
|
-
super(core)
|
|
62
|
-
this.settingsUpdate()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
63
|
/**
|
|
66
64
|
* @internal
|
|
67
65
|
*/
|
|
68
66
|
override bindEvents() {
|
|
67
|
+
this.listenTo(this.core, Events.CORE_READY, this.onCoreReady)
|
|
68
|
+
this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.render)
|
|
69
|
+
this.listenTo(
|
|
70
|
+
this.core,
|
|
71
|
+
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
72
|
+
this.bindContainerEvents,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private onCoreReady() {
|
|
69
77
|
const mediaControl = this.core.getPlugin('media_control')
|
|
70
78
|
assert(mediaControl, 'media_control plugin is required')
|
|
71
79
|
this.listenTo(
|
|
@@ -73,12 +81,7 @@ export class DvrControls extends UICorePlugin {
|
|
|
73
81
|
Events.MEDIACONTROL_RENDERED,
|
|
74
82
|
this.settingsUpdate,
|
|
75
83
|
)
|
|
76
|
-
this.
|
|
77
|
-
this.listenTo(
|
|
78
|
-
this.core,
|
|
79
|
-
Events.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
80
|
-
this.bindContainerEvents,
|
|
81
|
-
)
|
|
84
|
+
this.settingsUpdate()
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
private bindContainerEvents() {
|
|
@@ -94,57 +97,45 @@ export class DvrControls extends UICorePlugin {
|
|
|
94
97
|
)
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
private onDvrChanged(
|
|
100
|
+
private onDvrChanged(dvrInUse: boolean) {
|
|
98
101
|
trace(`${T} onDvrChanged`, {
|
|
99
|
-
|
|
102
|
+
dvrInUse,
|
|
100
103
|
})
|
|
101
104
|
if (this.core.getPlaybackType() !== Playback.LIVE) {
|
|
102
105
|
return
|
|
103
106
|
}
|
|
104
|
-
this.
|
|
105
|
-
this.core.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
this.render()
|
|
108
|
+
const mediaControl = this.core.getPlugin('media_control')
|
|
109
|
+
mediaControl.$el.addClass('live')
|
|
110
|
+
if (dvrInUse) {
|
|
111
|
+
mediaControl.$el
|
|
109
112
|
.addClass('dvr')
|
|
110
113
|
.find(
|
|
114
|
+
// TODO add API, test
|
|
111
115
|
'.media-control-indicator[data-position], .media-control-indicator[data-duration]',
|
|
112
116
|
)
|
|
113
117
|
.hide()
|
|
114
118
|
} else {
|
|
115
|
-
|
|
119
|
+
mediaControl.$el.removeClass('dvr')
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
private click() {
|
|
120
|
-
const mediaControl = this.core.getPlugin('media_control')
|
|
121
124
|
const container = this.core.activeContainer
|
|
122
|
-
|
|
123
125
|
if (!container.isPlaying()) {
|
|
124
126
|
container.play()
|
|
125
127
|
}
|
|
126
|
-
|
|
127
|
-
if (mediaControl.$el.hasClass('dvr')) {
|
|
128
|
-
container.seek(container.getDuration())
|
|
129
|
-
}
|
|
128
|
+
container.seek(container.getDuration())
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
private settingsUpdate() {
|
|
133
|
-
|
|
134
|
-
this.
|
|
135
|
-
this.
|
|
136
|
-
if (this.shouldRender()) {
|
|
137
|
-
this.render()
|
|
138
|
-
this.$el.click(() => this.click())
|
|
139
|
-
}
|
|
140
|
-
this.bindEvents()
|
|
132
|
+
trace(`${T} settingsUpdate`)
|
|
133
|
+
this.core.getPlugin('media_control').$el.removeClass('live')
|
|
134
|
+
this.render()
|
|
141
135
|
}
|
|
142
136
|
|
|
143
137
|
private shouldRender() {
|
|
144
|
-
const useDvrControls =
|
|
145
|
-
this.core.options.useDvrControls === undefined ||
|
|
146
|
-
!!this.core.options.useDvrControls
|
|
147
|
-
|
|
138
|
+
const useDvrControls = this.core.options.useDvrControls !== false
|
|
148
139
|
return useDvrControls && this.core.getPlaybackType() === Playback.LIVE
|
|
149
140
|
}
|
|
150
141
|
|
|
@@ -154,6 +145,7 @@ export class DvrControls extends UICorePlugin {
|
|
|
154
145
|
override render() {
|
|
155
146
|
trace(`${T} render`, {
|
|
156
147
|
dvrEnabled: this.core.activePlayback?.dvrEnabled,
|
|
148
|
+
playbackType: this.core.getPlaybackType(),
|
|
157
149
|
})
|
|
158
150
|
if (!this.shouldRender()) {
|
|
159
151
|
return this
|
|
@@ -164,13 +156,9 @@ export class DvrControls extends UICorePlugin {
|
|
|
164
156
|
backToLive: this.core.i18n.t('back_to_live'),
|
|
165
157
|
}),
|
|
166
158
|
)
|
|
167
|
-
const mediaControl = this.core.getPlugin('media_control')
|
|
168
|
-
assert(mediaControl, 'media_control plugin is required')
|
|
169
|
-
// TODO don't tap into the $el directly
|
|
159
|
+
const mediaControl = this.core.getPlugin('media_control') as MediaControl
|
|
170
160
|
mediaControl.$el.addClass('live')
|
|
171
|
-
mediaControl
|
|
172
|
-
.$('.media-control-left-panel[data-media-control]')
|
|
173
|
-
.append(this.$el)
|
|
161
|
+
mediaControl.getLeftPanel().append(this.$el)
|
|
174
162
|
|
|
175
163
|
return this
|
|
176
164
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { DvrControls } from '../DvrControls.js'
|
|
3
|
+
import { createMockCore, createMockMediaControl } from '../../../testUtils.js'
|
|
4
|
+
// import { LogTracer, Logger, setTracer } from '@gcorevideo/utils'
|
|
5
|
+
|
|
6
|
+
// setTracer(new LogTracer('DvrControls.test'))
|
|
7
|
+
// Logger.enable('*')
|
|
8
|
+
|
|
9
|
+
describe('DvrControls', () => {
|
|
10
|
+
let core: any
|
|
11
|
+
let mediaControl: any
|
|
12
|
+
let plugins: Record<string, any> = {}
|
|
13
|
+
let dvrControls: DvrControls
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
core = createMockCore()
|
|
16
|
+
mediaControl = createMockMediaControl(core)
|
|
17
|
+
plugins = {
|
|
18
|
+
media_control: mediaControl,
|
|
19
|
+
}
|
|
20
|
+
core.getPlugin.mockImplementation((name: string) => plugins[name])
|
|
21
|
+
dvrControls = new DvrControls(core)
|
|
22
|
+
plugins.dvr_controls = dvrControls
|
|
23
|
+
})
|
|
24
|
+
describe('live stream', () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
core.getPlaybackType.mockReturnValue('live')
|
|
27
|
+
})
|
|
28
|
+
describe.each([
|
|
29
|
+
['no DVR', false, false, false],
|
|
30
|
+
['DVR at live edge', true, false, false],
|
|
31
|
+
['DVR behind live edge', true, true, true],
|
|
32
|
+
])('%s', (_, dvrEnabled, dvrInUse, indicateDvr) => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
core.activePlayback.dvrEnabled = dvrEnabled
|
|
35
|
+
core.trigger('core:ready')
|
|
36
|
+
core.trigger('core:active:container:changed')
|
|
37
|
+
if (dvrInUse) {
|
|
38
|
+
core.activeContainer.trigger('container:dvr', true)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
it('should render', () => {
|
|
42
|
+
expect(dvrControls.el.textContent).toBeTruthy()
|
|
43
|
+
expect(dvrControls.el.innerHTML).toMatchSnapshot()
|
|
44
|
+
})
|
|
45
|
+
it('should render to the media control left panel', () => {
|
|
46
|
+
expect(mediaControl.$el.find('.media-control-left-panel').text()).toContain('live')
|
|
47
|
+
expect(mediaControl.el.innerHTML).toMatchSnapshot()
|
|
48
|
+
})
|
|
49
|
+
it('should indicate live streaming mode', () => {
|
|
50
|
+
expect(mediaControl.$el.hasClass('live')).toBe(true)
|
|
51
|
+
})
|
|
52
|
+
if (indicateDvr) {
|
|
53
|
+
it('should indicate DVR mode', () => {
|
|
54
|
+
expect(mediaControl.$el.hasClass('dvr')).toBe(true)
|
|
55
|
+
})
|
|
56
|
+
} else {
|
|
57
|
+
it('should not indicate DVR mode', () => {
|
|
58
|
+
expect(mediaControl.$el.hasClass('dvr')).toBe(false)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
describe('when back_to_live button is clicked', () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
core.activePlayback.dvrEnabled = true
|
|
65
|
+
core.trigger('core:ready')
|
|
66
|
+
core.trigger('core:active:container:changed')
|
|
67
|
+
core.activeContainer.getDuration.mockReturnValue(180)
|
|
68
|
+
core.activeContainer.trigger('container:dvr', true)
|
|
69
|
+
dvrControls.$el.find('.live-button').click()
|
|
70
|
+
})
|
|
71
|
+
it('should call active container play', () => {
|
|
72
|
+
expect(core.activeContainer.play).toHaveBeenCalled()
|
|
73
|
+
})
|
|
74
|
+
it('should seek to live edge', () => {
|
|
75
|
+
expect(core.activeContainer.seek).toHaveBeenCalledWith(180)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
describe('VOD stream', () => {
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
core.getPlaybackType.mockReturnValue('vod')
|
|
82
|
+
})
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
core.trigger('core:ready')
|
|
85
|
+
core.trigger('core:active:container:changed')
|
|
86
|
+
})
|
|
87
|
+
it('should not render', () => {
|
|
88
|
+
expect(dvrControls.el.textContent).toBeFalsy()
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`DvrControls > live stream > DVR at live edge > should render 1`] = `
|
|
4
|
+
"<div class="live-info">live</div>
|
|
5
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
6
|
+
"
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
exports[`DvrControls > live stream > DVR at live edge > should render to the media control left panel 1`] = `
|
|
10
|
+
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
11
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
12
|
+
</div></div>
|
|
13
|
+
<div class="media-control-right-panel" data-media-control=""></div>
|
|
14
|
+
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
exports[`DvrControls > live stream > DVR behind live edge > should render 1`] = `
|
|
18
|
+
"<div class="live-info">live</div>
|
|
19
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
20
|
+
"
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
exports[`DvrControls > live stream > DVR behind live edge > should render to the media control left panel 1`] = `
|
|
24
|
+
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
25
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
26
|
+
</div></div>
|
|
27
|
+
<div class="media-control-right-panel" data-media-control=""></div>
|
|
28
|
+
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
exports[`DvrControls > live stream > no DVR > should render 1`] = `
|
|
32
|
+
"<div class="live-info">live</div>
|
|
33
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
34
|
+
"
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
exports[`DvrControls > live stream > no DVR > should render to the media control left panel 1`] = `
|
|
38
|
+
"<div class="media-control-left-panel" data-media-control=""><div class="dvr-controls" data-dvr-controls=""><div class="live-info">live</div>
|
|
39
|
+
<button type="button" class="live-button" aria-label="back_to_live">back_to_live</button>
|
|
40
|
+
</div></div>
|
|
41
|
+
<div class="media-control-right-panel" data-media-control=""></div>
|
|
42
|
+
<div class="media-control-center-panel" data-media-control=""></div>"
|
|
43
|
+
`;
|
|
@@ -6,25 +6,7 @@ import { CLAPPR_VERSION } from '../../build.js'
|
|
|
6
6
|
import reloadIcon from '../../../assets/icons/old/reload.svg'
|
|
7
7
|
import templateHtml from '../../../assets/error-screen/error_screen.ejs'
|
|
8
8
|
import '../../../assets/error-screen/error_screen.scss'
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* An error fired in the player and plugins code to be handled in the UI
|
|
13
|
-
* @beta
|
|
14
|
-
*/
|
|
15
|
-
export type ErrorDesc = {
|
|
16
|
-
description: string
|
|
17
|
-
level: string
|
|
18
|
-
code: string
|
|
19
|
-
origin: string
|
|
20
|
-
scope: string
|
|
21
|
-
raw?: string
|
|
22
|
-
UI?: {
|
|
23
|
-
icon?: string
|
|
24
|
-
title: string
|
|
25
|
-
message: string
|
|
26
|
-
}
|
|
27
|
-
}
|
|
9
|
+
import { PlaybackError } from '../../playback.types.js'
|
|
28
10
|
|
|
29
11
|
type ErrorScreenDesc = {
|
|
30
12
|
title: string
|
|
@@ -47,7 +29,7 @@ export type ErrorScreenPluginSettings = {
|
|
|
47
29
|
const T = 'plugins.error_screen'
|
|
48
30
|
|
|
49
31
|
/**
|
|
50
|
-
* PLUGIN that displays errors nicely in the overlay on top of the player.
|
|
32
|
+
* `PLUGIN` that displays errors nicely in the overlay on top of the player.
|
|
51
33
|
* @beta
|
|
52
34
|
*/
|
|
53
35
|
export class ErrorScreen extends UICorePlugin {
|
|
@@ -142,7 +124,7 @@ export class ErrorScreen extends UICorePlugin {
|
|
|
142
124
|
}
|
|
143
125
|
}
|
|
144
126
|
|
|
145
|
-
private onError(err:
|
|
127
|
+
private onError(err: PlaybackError) {
|
|
146
128
|
trace(`${T} onError`, { err })
|
|
147
129
|
if (err.UI) {
|
|
148
130
|
if (this.err) {
|
|
@@ -172,7 +154,6 @@ export class ErrorScreen extends UICorePlugin {
|
|
|
172
154
|
}),
|
|
173
155
|
)
|
|
174
156
|
|
|
175
|
-
// TODO append to container instead of core?
|
|
176
157
|
if (!this.el.parentElement) {
|
|
177
158
|
this.core.$el.append(this.el)
|
|
178
159
|
}
|
|
@@ -10,15 +10,23 @@ import stopIcon from '../../../assets/icons/new/stop.svg';
|
|
|
10
10
|
const FAVICON_COLOR = '#567';
|
|
11
11
|
const FAVICON_SELECTOR = 'link[rel="shortcut icon"]';
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @beta
|
|
15
|
+
*/
|
|
16
|
+
export interface FaviconPluginSettings {
|
|
17
|
+
/**
|
|
18
|
+
* CSS color of the favicon.
|
|
19
|
+
*/
|
|
20
|
+
faviconColor?: string;
|
|
21
|
+
}
|
|
14
22
|
|
|
15
23
|
/**
|
|
16
|
-
*
|
|
24
|
+
* `PLUGIN` that changes the favicon according to the player's state.
|
|
17
25
|
* @beta
|
|
26
|
+
* @remarks
|
|
27
|
+
* There are three states: stopped, playing and paused.
|
|
18
28
|
*/
|
|
19
29
|
export class Favicon extends CorePlugin {
|
|
20
|
-
private _container: Container | null = null;
|
|
21
|
-
|
|
22
30
|
private oldIcon: ZeptoResult;
|
|
23
31
|
|
|
24
32
|
private playIcon: ZeptoResult | null = null;
|
|
@@ -27,18 +35,23 @@ export class Favicon extends CorePlugin {
|
|
|
27
35
|
|
|
28
36
|
private stopIcon: ZeptoResult | null = null;
|
|
29
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
30
41
|
get name() {
|
|
31
42
|
return 'favicon';
|
|
32
43
|
}
|
|
33
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
34
48
|
get supportedVersion() {
|
|
35
49
|
return { min: CLAPPR_VERSION };
|
|
36
50
|
}
|
|
37
51
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
42
55
|
constructor(core: Core) {
|
|
43
56
|
super(core);
|
|
44
57
|
this.oldIcon = $(FAVICON_SELECTOR);
|
|
@@ -46,45 +59,35 @@ export class Favicon extends CorePlugin {
|
|
|
46
59
|
this.stopIcon = this.createIcon(stopIcon);
|
|
47
60
|
this.changeIcon(this.stopIcon);
|
|
48
61
|
}
|
|
49
|
-
this.configure();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
configure() {
|
|
53
|
-
if (this.core.options.changeFavicon) {
|
|
54
|
-
if (!this.enabled) {
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
this.stopListening(this.core, Events.CORE_OPTIONS_CHANGE);
|
|
57
|
-
this.enable();
|
|
58
|
-
}
|
|
59
|
-
} else if (this.enabled) {
|
|
60
|
-
this.disable();
|
|
61
|
-
this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.configure);
|
|
62
|
-
}
|
|
63
62
|
}
|
|
64
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
65
67
|
override bindEvents() {
|
|
66
|
-
this.listenTo(this.core, Events.CORE_OPTIONS_CHANGE, this.configure);
|
|
67
68
|
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.containerChanged);
|
|
68
|
-
this.core.activeContainer && this.containerChanged();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
private containerChanged() {
|
|
72
|
-
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
this.listenTo(this.
|
|
76
|
-
this.listenTo(this.
|
|
77
|
-
this.listenTo(this._container, Events.CONTAINER_STOP, this.resetIcon);
|
|
78
|
-
this.listenTo(this._container, Events.CONTAINER_ENDED, this.resetIcon);
|
|
79
|
-
this.listenTo(this._container, Events.CONTAINER_ERROR, this.resetIcon);
|
|
72
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_PLAY, this.setPlayIcon);
|
|
73
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_PAUSE, this.setPauseIcon);
|
|
74
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_STOP, this.resetIcon);
|
|
75
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_ENDED, this.resetIcon);
|
|
76
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_ERROR, this.resetIcon);
|
|
80
77
|
this.resetIcon();
|
|
81
78
|
}
|
|
82
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
83
|
override disable() {
|
|
84
84
|
super.disable();
|
|
85
85
|
this.resetIcon();
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
88
91
|
override destroy() {
|
|
89
92
|
super.destroy();
|
|
90
93
|
this.resetIcon();
|
|
@@ -113,7 +116,6 @@ export class Favicon extends CorePlugin {
|
|
|
113
116
|
if (!this.playIcon) {
|
|
114
117
|
this.playIcon = this.createIcon(playIcon);
|
|
115
118
|
}
|
|
116
|
-
|
|
117
119
|
this.changeIcon(this.playIcon);
|
|
118
120
|
}
|
|
119
121
|
|
|
@@ -121,21 +123,16 @@ export class Favicon extends CorePlugin {
|
|
|
121
123
|
if (!this.pauseIcon) {
|
|
122
124
|
this.pauseIcon = this.createIcon(pauseIcon);
|
|
123
125
|
}
|
|
124
|
-
|
|
125
126
|
this.changeIcon(this.pauseIcon);
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
private resetIcon() {
|
|
129
|
-
$(FAVICON_SELECTOR).remove();
|
|
130
130
|
const icon = this.oldIcon.length > 0 ? this.oldIcon : this.stopIcon;
|
|
131
|
-
|
|
132
131
|
this.changeIcon(icon);
|
|
133
132
|
}
|
|
134
133
|
|
|
135
|
-
private changeIcon(icon: ZeptoResult
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
$('head').append(icon);
|
|
139
|
-
}
|
|
134
|
+
private changeIcon(icon: ZeptoResult) {
|
|
135
|
+
$('link[rel="shortcut icon"]').remove();
|
|
136
|
+
$('head').append(icon);
|
|
140
137
|
}
|
|
141
138
|
}
|
|
@@ -40,7 +40,7 @@ export interface LevelSelectorPluginSettings {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* PLUGIN that provides a UI to select the desired quality level of the playback.
|
|
43
|
+
* `PLUGIN` that provides a UI to select the desired quality level of the playback.
|
|
44
44
|
* @beta
|
|
45
45
|
*
|
|
46
46
|
* @remarks
|
package/src/plugins/logo/Logo.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
// This is a derived work from the {@link https://github.com/clappr/clappr-plugins/tree/ffaa9d27005fa5a8a7c243ffc47eb5655b84b371/src/plugins/media_control | Clappr MediaControl plugin}
|
|
2
|
+
// It is redistributed under the terms of the {@link ../../../../../LICENSE | Apache 2.0} license.
|
|
1
3
|
// Copyright 2014 Globo.com Player authors. All rights reserved.
|
|
2
4
|
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE
|
|
5
|
+
// license that can be found in the {@link https://github.com/clappr/clappr-plugins/blob/master/LICENSE | LICENSE}.
|
|
4
6
|
|
|
5
7
|
import assert from 'assert'
|
|
6
8
|
import {
|
|
@@ -88,11 +90,11 @@ type DisabledClickable = {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
/**
|
|
91
|
-
* PLUGIN that provides a foundation for developing custom media controls UI.
|
|
93
|
+
* `PLUGIN` that provides a foundation for developing custom media controls UI.
|
|
92
94
|
* @beta
|
|
93
95
|
* @remarks
|
|
94
96
|
* The methods exposed are to be used by the other plugins that extend the media control UI.
|
|
95
|
-
* The plugin registration should be arranged so that MediaControl is initialized before every other
|
|
97
|
+
* The plugin registration should be arranged so that MediaControl is initialized before every other `PLUGIN` that depends on it.
|
|
96
98
|
* @example
|
|
97
99
|
* ```ts
|
|
98
100
|
* Player.registerPlugin(MediaControl) // <--- This must go first
|
|
@@ -1132,6 +1134,18 @@ export class MediaControl extends UICorePlugin {
|
|
|
1132
1134
|
return this.$el.find('.media-control-right-panel')
|
|
1133
1135
|
}
|
|
1134
1136
|
|
|
1137
|
+
/**
|
|
1138
|
+
* Get the left panel area to append custom elements to
|
|
1139
|
+
* @returns ZeptoSelector of the left panel element
|
|
1140
|
+
*/
|
|
1141
|
+
getLeftPanel() {
|
|
1142
|
+
return this.$el.find('.media-control-left-panel')
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
getCenterPanel() {
|
|
1146
|
+
return this.$el.find('.media-control-center-panel')
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1135
1149
|
private resetIndicators() {
|
|
1136
1150
|
assert.ok(
|
|
1137
1151
|
this.$duration && this.$position,
|
|
@@ -26,7 +26,7 @@ const VERSION = '0.0.1';
|
|
|
26
26
|
const T = 'plugins.multicamera';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* PLUGIN that adds support for loading multiple streams and switching between them using the media control UI.
|
|
29
|
+
* `PLUGIN` that adds support for loading multiple streams and switching between them using the media control UI.
|
|
30
30
|
* @beta
|
|
31
31
|
*/
|
|
32
32
|
export class MultiCamera extends UICorePlugin {
|
|
@@ -24,7 +24,7 @@ import { PlaybackError } from '../../playback.types.js'
|
|
|
24
24
|
const T = 'plugins.poster'
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* `PLUGIN` that displays a poster image in the background and a big play button on top when playback is stopped
|
|
28
28
|
* @beta
|
|
29
29
|
* @remarks
|
|
30
30
|
* When the playback is stopped, media control UI is disabled.
|
|
@@ -14,7 +14,7 @@ import { ZeptoResult } from '../../types.js';
|
|
|
14
14
|
const { formatTime } = Utils;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* `PLUGIN` that adds a seek time indicator to the media control UI.
|
|
18
18
|
* @beta
|
|
19
19
|
*/
|
|
20
20
|
export class SeekTime extends UICorePlugin {
|
|
@@ -10,7 +10,7 @@ import fbIcon from '../../../assets/icons/old/fb.svg';
|
|
|
10
10
|
import twIcon from '../../../assets/icons/old/twitter.svg';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* PLUGIN that adds a share button to the media control UI.
|
|
13
|
+
* `PLUGIN` that adds a share button to the media control UI.
|
|
14
14
|
* @beta
|
|
15
15
|
*/
|
|
16
16
|
export class Share extends UICorePlugin {
|
|
@@ -8,7 +8,7 @@ import '../../../assets/skip-time/style.scss';
|
|
|
8
8
|
type Position = 'mid' | 'left' | 'right';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* PLUGIN that adds skip controls to the media control UI.
|
|
11
|
+
* `PLUGIN` that adds skip controls to the media control UI.
|
|
12
12
|
* @beta
|
|
13
13
|
*/
|
|
14
14
|
export class SkipTime extends UICorePluginOriginal {
|
|
@@ -27,7 +27,7 @@ function noSync(cb: () => void) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* `PLUGIN` that is responsible for managing the automatic failover between sources.
|
|
31
31
|
* @beta
|
|
32
32
|
* @remarks
|
|
33
33
|
* Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
|
|
@@ -31,7 +31,7 @@ export enum SpinnerEvents {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* PLUGIN that shows a pending operation indicator when playback is buffering or in a similar state
|
|
34
|
+
* `PLUGIN` that shows a pending operation indicator when playback is buffering or in a similar state
|
|
35
35
|
* @beta
|
|
36
36
|
* @remarks
|
|
37
37
|
* Events emitted- {@link SpinnerEvents}
|
|
@@ -34,7 +34,7 @@ type TextTrackInfo = {
|
|
|
34
34
|
const NO_TRACK = { language: 'off' }
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* `PLUGIN` that provides a UI to select the subtitles when available.
|
|
38
38
|
* @beta
|
|
39
39
|
*
|
|
40
40
|
* @remarks
|