@gcorevideo/player 2.22.14 → 2.22.16
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/clips/clips.ejs +1 -0
- package/assets/clips/clips.scss +23 -3
- package/assets/context-menu/context_menu.ejs +14 -6
- package/assets/context-menu/context_menu.scss +18 -4
- package/assets/level-selector/list.ejs +9 -3
- package/assets/media-control/media-control.ejs +1 -9
- package/assets/media-control/media-control.scss +0 -25
- package/assets/media-control/width370.scss +4 -4
- package/dist/core.js +5 -23
- package/dist/index.css +424 -412
- package/dist/index.js +294 -286
- package/dist/player.d.ts +211 -144
- package/dist/plugins/index.css +1513 -1501
- package/dist/plugins/index.js +224 -227
- package/docs/api/{player.audioselector.md → player.audiotracks.md} +3 -3
- package/docs/api/player.contextmenu.md +2 -0
- package/docs/api/player.contextmenupluginsettings.md +2 -40
- package/docs/api/{player.contextmenupluginsettings.label.md → player.contextmenupluginsettings.options.md} +3 -3
- package/docs/api/player.md +78 -23
- package/docs/api/player.mediacontrol.md +8 -14
- package/docs/api/player.mediacontrolelement.md +4 -2
- package/docs/api/{player.contextmenupluginsettings.preventshowcontextmenu.md → player.mediacontrollayerelement.md} +5 -3
- package/docs/api/player.mediacontrolleftelement.md +16 -0
- package/docs/api/player.mediacontrolrightelement.md +16 -0
- package/docs/api/player.mediacontrolsettings.md +23 -0
- package/docs/api/{player.contextmenupluginsettings.url.md → player.menuoption.md} +10 -3
- package/docs/api/player.playbackrate.md +1 -1
- package/docs/api/player.playerconfig.md +1 -1
- package/docs/api/player.playerconfig.playbacktype.md +1 -1
- package/docs/api/{player.levelselector.events.md → player.qualitylevels.events.md} +2 -2
- package/docs/api/{player.levelselector.md → player.qualitylevels.md} +6 -6
- package/docs/api/{player.levelselectorpluginsettings.labels.md → player.qualitylevelspluginsettings.labels.md} +2 -2
- package/docs/api/{player.levelselectorpluginsettings.md → player.qualitylevelspluginsettings.md} +6 -6
- package/docs/api/{player.levelselectorpluginsettings.restrictresolution.md → player.qualitylevelspluginsettings.restrictresolution.md} +2 -2
- package/lib/Player.d.ts.map +1 -1
- package/lib/Player.js +4 -1
- package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/playback/hls-playback/HlsPlayback.js +0 -21
- package/lib/plugins/click-to-pause/ClickToPause.js +1 -1
- package/lib/plugins/clips/Clips.d.ts +21 -16
- package/lib/plugins/clips/Clips.d.ts.map +1 -1
- package/lib/plugins/clips/Clips.js +96 -98
- package/lib/plugins/clips/types.d.ts +19 -0
- package/lib/plugins/clips/types.d.ts.map +1 -0
- package/lib/plugins/clips/types.js +1 -0
- package/lib/plugins/clips/utils.d.ts +4 -0
- package/lib/plugins/clips/utils.d.ts.map +1 -0
- package/lib/plugins/clips/utils.js +36 -0
- package/lib/plugins/context-menu/ContextMenu.d.ts +33 -12
- package/lib/plugins/context-menu/ContextMenu.d.ts.map +1 -1
- package/lib/plugins/context-menu/ContextMenu.js +40 -37
- package/lib/plugins/media-control/MediaControl.d.ts +4 -7
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +19 -31
- package/lib/plugins/utils.d.ts +9 -1
- package/lib/plugins/utils.d.ts.map +1 -1
- package/lib/plugins/utils.js +9 -10
- package/lib/plugins/vast-ads/loaderxml.js +2 -2
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +2 -5
- package/package.json +1 -1
- package/src/Player.ts +4 -3
- package/src/playback/hls-playback/HlsPlayback.ts +0 -22
- package/src/plugins/click-to-pause/ClickToPause.ts +1 -1
- package/src/plugins/clips/Clips.ts +116 -135
- package/src/plugins/clips/__tests__/Clips.test.ts +72 -0
- package/src/plugins/clips/__tests__/__snapshots__/Clips.test.ts.snap +14 -0
- package/src/plugins/clips/types.ts +22 -0
- package/src/plugins/clips/utils.ts +54 -0
- package/src/plugins/context-menu/ContextMenu.ts +72 -56
- package/src/plugins/level-selector/__tests__/__snapshots__/QualityLevels.test.ts.snap +18 -18
- package/src/plugins/media-control/MediaControl.ts +31 -58
- package/src/plugins/media-control/__tests__/MediaControl.test.ts +66 -30
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +7 -35
- package/src/plugins/utils.ts +9 -7
- package/src/plugins/vast-ads/loaderxml.ts +2 -2
- package/src/testUtils.ts +2 -5
- package/temp/player.api.json +332 -262
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.mediacontrol.handlecustomarea.md +0 -52
|
@@ -386,16 +386,6 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
386
386
|
this.seek(seekTo);
|
|
387
387
|
}
|
|
388
388
|
seek(time) {
|
|
389
|
-
// trace(`${T} seek`, {
|
|
390
|
-
// time,
|
|
391
|
-
// duration: this._duration,
|
|
392
|
-
// startTime: this._startTime,
|
|
393
|
-
// currentTimestamp: this.currentTimestamp,
|
|
394
|
-
// playbackType: this.getPlaybackType(),
|
|
395
|
-
// dvrEnabled: this.dvrEnabled,
|
|
396
|
-
// durationExcludesAfterLiveSyncPoint: this._durationExcludesAfterLiveSyncPoint,
|
|
397
|
-
// minDvrSize: this._minDvrSize,
|
|
398
|
-
// })
|
|
399
389
|
if (time < 0) {
|
|
400
390
|
Log.warn('Attempt to seek to a negative time. Resetting to live point. Use seekToLivePoint() to seek to the live point.');
|
|
401
391
|
time = this.getDuration();
|
|
@@ -547,11 +537,6 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
547
537
|
return;
|
|
548
538
|
}
|
|
549
539
|
this._lastTimeUpdate = update;
|
|
550
|
-
// trace(`${T} _onTimeUpdate`, {
|
|
551
|
-
// current: update.current,
|
|
552
|
-
// total: update.total,
|
|
553
|
-
// firstFragDateTime: update.firstFragDateTime,
|
|
554
|
-
// })
|
|
555
540
|
this.trigger(Events.PLAYBACK_TIMEUPDATE, update, this.name);
|
|
556
541
|
}
|
|
557
542
|
_onDurationChange() {
|
|
@@ -823,12 +808,6 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
823
808
|
this.trigger(Events.PLAYBACK_LEVEL_SWITCH_END);
|
|
824
809
|
}
|
|
825
810
|
get dvrEnabled() {
|
|
826
|
-
// trace(`${T} dvrEnabled`, {
|
|
827
|
-
// durationExcludesAfterLiveSyncPoint: this._durationExcludesAfterLiveSyncPoint,
|
|
828
|
-
// duration: this._duration,
|
|
829
|
-
// minDvrSize: this._minDvrSize,
|
|
830
|
-
// playbackType: this.getPlaybackType(),
|
|
831
|
-
// })
|
|
832
811
|
// enabled when:
|
|
833
812
|
// - the duration does not include content after hlsjs's live sync point
|
|
834
813
|
// - the playable region duration is longer than the configured duration to enable dvr after
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { ContainerPlugin, Events, Playback } from '@clappr/core';
|
|
6
6
|
import { trace } from '@gcorevideo/utils';
|
|
7
7
|
import { CLAPPR_VERSION } from '../../build.js';
|
|
8
|
-
const T = 'plugins.
|
|
8
|
+
const T = 'plugins.click_to_pause';
|
|
9
9
|
/**
|
|
10
10
|
* A small `PLUGIN` that toggles the playback state on click over the video container
|
|
11
11
|
* @beta
|
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
import { UICorePlugin } from '@clappr/core';
|
|
2
2
|
import '../../../assets/clips/clips.scss';
|
|
3
3
|
/**
|
|
4
|
-
* Configuration options for the {@link ClipsPlugin
|
|
4
|
+
* Configuration options for the {@link ClipsPlugin} plugin.
|
|
5
5
|
* @beta
|
|
6
6
|
*/
|
|
7
7
|
export interface ClipsPluginSettings {
|
|
8
8
|
/**
|
|
9
|
-
* The text
|
|
9
|
+
* The compiled text of the clips description, one clip per line in format :
|
|
10
|
+
* `HH:MM:SS text` or `MM:SS text` or `SS text`
|
|
10
11
|
*/
|
|
11
12
|
text: string;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
* `PLUGIN` that
|
|
15
|
+
* `PLUGIN` that allows marking up the timeline of the video
|
|
15
16
|
* @beta
|
|
16
17
|
* @remarks
|
|
18
|
+
* The plugin decorates the seekbar with notches to indicate the clips of the video and displays current clip text in the left panel
|
|
19
|
+
*
|
|
17
20
|
* Depends on:
|
|
18
21
|
*
|
|
19
22
|
* - {@link MediaControl}
|
|
20
23
|
*
|
|
21
24
|
* Configuration options - {@link ClipsPluginSettings}
|
|
22
25
|
*/
|
|
23
|
-
export declare class
|
|
26
|
+
export declare class Clips extends UICorePlugin {
|
|
27
|
+
private barStyle;
|
|
24
28
|
private clips;
|
|
25
|
-
private
|
|
26
|
-
private durationGetting;
|
|
27
|
-
private _oldContainer;
|
|
29
|
+
private oldContainer;
|
|
28
30
|
private svgMask;
|
|
31
|
+
private static readonly template;
|
|
29
32
|
/**
|
|
30
33
|
* @internal
|
|
31
34
|
*/
|
|
@@ -36,22 +39,24 @@ export declare class ClipsPlugin extends UICorePlugin {
|
|
|
36
39
|
get attributes(): {
|
|
37
40
|
class: string;
|
|
38
41
|
};
|
|
42
|
+
get version(): string;
|
|
43
|
+
get supportedVersion(): {
|
|
44
|
+
min: string;
|
|
45
|
+
};
|
|
39
46
|
/**
|
|
40
47
|
* @internal
|
|
41
48
|
*/
|
|
42
49
|
bindEvents(): void;
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
render(): this;
|
|
51
|
+
destroy(): import("@clappr/core").UIObject;
|
|
52
|
+
disable(): void;
|
|
53
|
+
enable(): void;
|
|
54
|
+
private onCoreReady;
|
|
55
|
+
private onMcRender;
|
|
56
|
+
private onContainerChanged;
|
|
45
57
|
private playerResize;
|
|
46
|
-
private _bindContainerEvents;
|
|
47
58
|
private onTimeUpdate;
|
|
48
59
|
private parseClips;
|
|
49
|
-
/**
|
|
50
|
-
* Returns the text of the current clip.
|
|
51
|
-
* @param time - The current time of the player.
|
|
52
|
-
* @returns The text of the current clip.
|
|
53
|
-
*/
|
|
54
|
-
getText(time: number): string;
|
|
55
60
|
private makeSvg;
|
|
56
61
|
private setSVGMask;
|
|
57
62
|
private setClipText;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Clips.d.ts","sourceRoot":"","sources":["../../../src/plugins/clips/Clips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,
|
|
1
|
+
{"version":3,"file":"Clips.d.ts","sourceRoot":"","sources":["../../../src/plugins/clips/Clips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAe,MAAM,cAAc,CAAA;AAM3E,OAAO,kCAAkC,CAAA;AAOzC;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;CACb;AAKD;;;;;;;;;;;GAWG;AACH,qBAAa,KAAM,SAAQ,YAAY;IACrC,OAAO,CAAC,QAAQ,CAAgC;IAEhD,OAAO,CAAC,KAAK,CAAiB;IAE9B,OAAO,CAAC,YAAY,CAAuB;IAE3C,OAAO,CAAC,OAAO,CAA2B;IAE1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAEtD;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAa,UAAU;;MAItB;IAED,IAAI,OAAO,WAEV;IAED,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACM,UAAU;IAUV,MAAM;IAUN,OAAO;IAQP,OAAO;IAQP,MAAM;IAKf,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,kBAAkB;IAsB1B,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
import { Events, UICorePlugin,
|
|
2
|
-
import {
|
|
3
|
-
import '../../../assets/clips/clips.scss';
|
|
1
|
+
import { Events, UICorePlugin, $, template } from '@clappr/core';
|
|
2
|
+
import { trace } from '@gcorevideo/utils';
|
|
4
3
|
import assert from 'assert';
|
|
4
|
+
import '../../../assets/clips/clips.scss';
|
|
5
|
+
import { buildSvg, parseClips } from './utils.js';
|
|
6
|
+
import clipsHTML from '../../../assets/clips/clips.ejs';
|
|
7
|
+
const T = 'plugins.clips';
|
|
8
|
+
const VERSION = '2.22.16';
|
|
9
|
+
const CLAPPR_VERSION = '0.11.4';
|
|
5
10
|
/**
|
|
6
|
-
* `PLUGIN` that
|
|
11
|
+
* `PLUGIN` that allows marking up the timeline of the video
|
|
7
12
|
* @beta
|
|
8
13
|
* @remarks
|
|
14
|
+
* The plugin decorates the seekbar with notches to indicate the clips of the video and displays current clip text in the left panel
|
|
15
|
+
*
|
|
9
16
|
* Depends on:
|
|
10
17
|
*
|
|
11
18
|
* - {@link MediaControl}
|
|
12
19
|
*
|
|
13
20
|
* Configuration options - {@link ClipsPluginSettings}
|
|
14
21
|
*/
|
|
15
|
-
export class
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
_oldContainer;
|
|
22
|
+
export class Clips extends UICorePlugin {
|
|
23
|
+
barStyle = null;
|
|
24
|
+
clips = [];
|
|
25
|
+
oldContainer;
|
|
20
26
|
svgMask = null;
|
|
27
|
+
static template = template(clipsHTML);
|
|
21
28
|
/**
|
|
22
29
|
* @internal
|
|
23
30
|
*/
|
|
@@ -29,130 +36,121 @@ export class ClipsPlugin extends UICorePlugin {
|
|
|
29
36
|
*/
|
|
30
37
|
get attributes() {
|
|
31
38
|
return {
|
|
32
|
-
class:
|
|
39
|
+
class: 'media-control-clips',
|
|
33
40
|
};
|
|
34
41
|
}
|
|
42
|
+
get version() {
|
|
43
|
+
return VERSION;
|
|
44
|
+
}
|
|
45
|
+
get supportedVersion() {
|
|
46
|
+
return { min: CLAPPR_VERSION };
|
|
47
|
+
}
|
|
35
48
|
/**
|
|
36
49
|
* @internal
|
|
37
50
|
*/
|
|
38
51
|
bindEvents() {
|
|
39
|
-
|
|
40
|
-
assert(mediaControl, 'media_control plugin is required');
|
|
41
|
-
this.listenToOnce(this.core, Events.CORE_READY, this._onCoreReady);
|
|
42
|
-
// TODO listen to CORE_ACTIVE_CONTAINER_CHANGED
|
|
43
|
-
this.listenTo(mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this._onMediaControlContainerChanged);
|
|
52
|
+
this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
|
|
44
53
|
this.listenTo(this.core, Events.CORE_RESIZE, this.playerResize);
|
|
54
|
+
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
|
|
45
55
|
}
|
|
46
|
-
|
|
56
|
+
render() {
|
|
57
|
+
trace(`${T} render`);
|
|
47
58
|
if (!this.options.clips) {
|
|
48
|
-
this
|
|
49
|
-
return;
|
|
59
|
+
return this;
|
|
50
60
|
}
|
|
51
|
-
this.
|
|
61
|
+
this.$el.html(Clips.template());
|
|
62
|
+
this.$el.hide();
|
|
63
|
+
return this;
|
|
52
64
|
}
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.durationGetting = false;
|
|
58
|
-
if (this.durationGetting) {
|
|
59
|
-
this.makeSvg(this.duration);
|
|
65
|
+
destroy() {
|
|
66
|
+
if (this.barStyle) {
|
|
67
|
+
this.barStyle.remove();
|
|
68
|
+
this.barStyle = null;
|
|
60
69
|
}
|
|
70
|
+
return super.destroy();
|
|
61
71
|
}
|
|
62
|
-
|
|
63
|
-
if (this.
|
|
64
|
-
this.
|
|
72
|
+
disable() {
|
|
73
|
+
if (this.barStyle) {
|
|
74
|
+
this.barStyle.remove();
|
|
75
|
+
this.barStyle = null;
|
|
65
76
|
}
|
|
77
|
+
return super.disable();
|
|
78
|
+
}
|
|
79
|
+
enable() {
|
|
80
|
+
this.render();
|
|
81
|
+
return super.enable();
|
|
82
|
+
}
|
|
83
|
+
onCoreReady() {
|
|
84
|
+
trace(`${T} onCoreReady`);
|
|
85
|
+
const mediaControl = this.core.getPlugin('media_control');
|
|
86
|
+
assert(mediaControl, 'media_control plugin is required');
|
|
87
|
+
this.parseClips(this.options.clips.text);
|
|
88
|
+
this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.onMcRender);
|
|
89
|
+
}
|
|
90
|
+
onMcRender() {
|
|
91
|
+
trace(`${T} onMcRender`);
|
|
66
92
|
const mediaControl = this.core.getPlugin('media_control');
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
mediaControl.mount('clips', this.$el);
|
|
94
|
+
}
|
|
95
|
+
onContainerChanged() {
|
|
96
|
+
trace(`${T} onContainerChanged`);
|
|
97
|
+
// TODO figure out the conditions of changing the container (without destroying the previous one)
|
|
98
|
+
if (this.oldContainer) {
|
|
99
|
+
this.stopListening(this.oldContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
100
|
+
}
|
|
101
|
+
this.oldContainer = this.core.activeContainer;
|
|
102
|
+
if (this.svgMask) {
|
|
103
|
+
this.svgMask.remove();
|
|
104
|
+
this.svgMask = null;
|
|
105
|
+
}
|
|
106
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
107
|
+
}
|
|
108
|
+
playerResize() {
|
|
109
|
+
const duration = this.core.activeContainer.getDuration();
|
|
110
|
+
if (duration) {
|
|
111
|
+
this.makeSvg(duration);
|
|
112
|
+
}
|
|
70
113
|
}
|
|
71
114
|
onTimeUpdate(event) {
|
|
72
|
-
if (!this.
|
|
73
|
-
this.duration = event.total;
|
|
115
|
+
if (!this.svgMask) {
|
|
74
116
|
this.makeSvg(event.total);
|
|
75
|
-
this.durationGetting = true;
|
|
76
117
|
}
|
|
77
|
-
for (const value of this.clips
|
|
78
|
-
if (event.current >= value.start &&
|
|
118
|
+
for (const value of this.clips) {
|
|
119
|
+
if ((event.current >= value.start && !value.end) ||
|
|
120
|
+
event.current < value.end) {
|
|
79
121
|
this.setClipText(value.text);
|
|
80
122
|
break;
|
|
81
123
|
}
|
|
82
124
|
}
|
|
83
125
|
}
|
|
84
|
-
parseClips() {
|
|
85
|
-
|
|
86
|
-
const clipsArr = textArr
|
|
87
|
-
.map((val) => {
|
|
88
|
-
const matchRes = val.match(/(\d+:\d+|:\d+) (.+)/i);
|
|
89
|
-
return matchRes
|
|
90
|
-
? {
|
|
91
|
-
start: strtimeToMiliseconds(matchRes[1]),
|
|
92
|
-
text: matchRes[2],
|
|
93
|
-
}
|
|
94
|
-
: null;
|
|
95
|
-
})
|
|
96
|
-
.filter((clip) => clip !== null);
|
|
97
|
-
clipsArr.sort((a, b) => a.start - b.start);
|
|
98
|
-
clipsArr.forEach((clip, index) => {
|
|
99
|
-
this.clips.set(clip.start, {
|
|
100
|
-
index,
|
|
101
|
-
start: clip.start,
|
|
102
|
-
text: clip.text,
|
|
103
|
-
end: clipsArr[index + 1] ? clipsArr[index + 1].start : null,
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Returns the text of the current clip.
|
|
109
|
-
* @param time - The current time of the player.
|
|
110
|
-
* @returns The text of the current clip.
|
|
111
|
-
*/
|
|
112
|
-
getText(time) {
|
|
113
|
-
for (const [key, value] of this.clips.entries()) {
|
|
114
|
-
if (time >= value.start && time < value.end) {
|
|
115
|
-
return value.text;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return '';
|
|
126
|
+
parseClips(text) {
|
|
127
|
+
this.clips = parseClips(text);
|
|
119
128
|
}
|
|
120
129
|
makeSvg(duration) {
|
|
121
|
-
|
|
122
|
-
const widthOfSeek = this.core.activeContainer.$el.width();
|
|
123
|
-
let finishValue = 0;
|
|
124
|
-
this.clips.forEach((val) => {
|
|
125
|
-
let end = val.end;
|
|
126
|
-
if (!end) {
|
|
127
|
-
end = val.end = duration;
|
|
128
|
-
}
|
|
129
|
-
const widthChunk = ((end - val.start) * widthOfSeek) / duration;
|
|
130
|
-
svg += `<rect x="${finishValue}" y="0" width="${widthChunk - 2}" height="30"/>\n`;
|
|
131
|
-
finishValue += widthChunk;
|
|
132
|
-
});
|
|
133
|
-
svg += `<rect x="${finishValue}" y="0" width="${widthOfSeek - finishValue}" height="30"/>\n`;
|
|
134
|
-
svg += '</clipPath>' + '</defs>' + '</svg>';
|
|
130
|
+
const svg = buildSvg(this.clips, duration, this.core.activeContainer.$el.width());
|
|
135
131
|
this.setSVGMask(svg);
|
|
136
132
|
}
|
|
137
133
|
setSVGMask(svg) {
|
|
138
|
-
// this.core.mediaControl.setSVGMask(svg);
|
|
139
134
|
if (this.svgMask) {
|
|
140
135
|
this.svgMask.remove();
|
|
141
136
|
}
|
|
142
|
-
const mediaControl = this.core.getPlugin('media_control');
|
|
143
|
-
const $seekBarContainer = mediaControl.getElement('seekBarContainer');
|
|
144
|
-
if ($seekBarContainer?.get(0)) {
|
|
145
|
-
$seekBarContainer.addClass('clips');
|
|
146
|
-
}
|
|
147
137
|
this.svgMask = $(svg);
|
|
148
|
-
|
|
138
|
+
this.$el.append(this.svgMask);
|
|
139
|
+
if (!this.barStyle) {
|
|
140
|
+
this.barStyle = document.createElement('style');
|
|
141
|
+
this.barStyle.textContent = `
|
|
142
|
+
.bar-container[data-seekbar] {
|
|
143
|
+
clip-path: url("#myClip");
|
|
144
|
+
}`;
|
|
145
|
+
this.$el.append(this.barStyle);
|
|
146
|
+
}
|
|
149
147
|
}
|
|
150
148
|
setClipText(text) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
if (text) {
|
|
150
|
+
this.$el.show().find('#clips-text').text(text);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.$el.hide();
|
|
156
154
|
}
|
|
157
155
|
}
|
|
158
156
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clip description.
|
|
3
|
+
* @beta
|
|
4
|
+
*/
|
|
5
|
+
export type ClipDesc = {
|
|
6
|
+
/**
|
|
7
|
+
* Start time of the clip in the video timeline, s.
|
|
8
|
+
*/
|
|
9
|
+
start: number;
|
|
10
|
+
/**
|
|
11
|
+
* Text to display over the seekbar.
|
|
12
|
+
*/
|
|
13
|
+
text: string;
|
|
14
|
+
/**
|
|
15
|
+
* End time of the clip (start time of the next clip).
|
|
16
|
+
*/
|
|
17
|
+
end: number;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/plugins/clips/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;CAKZ,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/plugins/clips/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAQrC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmBnD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwBtF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { parseClipTime } from '../utils.js';
|
|
2
|
+
export function parseClips(text) {
|
|
3
|
+
const clipsArr = text
|
|
4
|
+
.split('\n')
|
|
5
|
+
.map((val) => {
|
|
6
|
+
const matchRes = val.match(/(((\d+:)?\d+:)?\d+) (.+)/i);
|
|
7
|
+
return matchRes
|
|
8
|
+
? {
|
|
9
|
+
start: parseClipTime(matchRes[1]),
|
|
10
|
+
text: matchRes[4],
|
|
11
|
+
}
|
|
12
|
+
: null;
|
|
13
|
+
})
|
|
14
|
+
.filter((clip) => clip !== null)
|
|
15
|
+
.sort((a, b) => a.start - b.start);
|
|
16
|
+
return clipsArr.map((clip, index) => ({
|
|
17
|
+
start: clip.start,
|
|
18
|
+
text: clip.text,
|
|
19
|
+
end: index < clipsArr.length - 1 ? clipsArr[index + 1].start : 0,
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
export function buildSvg(clips, duration, barWidth) {
|
|
23
|
+
let svg = '<svg width="0" height="0">\n' + '<defs>\n' + '<clipPath id="myClip">\n';
|
|
24
|
+
let rightEdge = 0;
|
|
25
|
+
clips.forEach((val) => {
|
|
26
|
+
const end = val.end || duration;
|
|
27
|
+
const chunkWidth = Math.round(((end - val.start) * barWidth) / duration);
|
|
28
|
+
svg += `<rect x="${rightEdge}" y="0" width="${chunkWidth - 2}" height="30"/>\n`;
|
|
29
|
+
rightEdge += chunkWidth;
|
|
30
|
+
});
|
|
31
|
+
if (rightEdge < barWidth) {
|
|
32
|
+
svg += `<rect x="${rightEdge}" y="0" width="${barWidth - rightEdge}" height="30"/>\n`;
|
|
33
|
+
}
|
|
34
|
+
svg += '</clipPath>' + '</defs>' + '</svg>';
|
|
35
|
+
return svg;
|
|
36
|
+
}
|
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
import { Container, UIContainerPlugin } from '@clappr/core';
|
|
2
2
|
import '../../../assets/context-menu/context_menu.scss';
|
|
3
|
+
/**
|
|
4
|
+
* @beta
|
|
5
|
+
*/
|
|
6
|
+
export type MenuOption = {
|
|
7
|
+
/**
|
|
8
|
+
* Menu item label text. One of `label` or `labelKey` must be specified.
|
|
9
|
+
*/
|
|
10
|
+
label?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Menu item label localisation key, if specified, the `label` will be ignored
|
|
13
|
+
*/
|
|
14
|
+
labelKey?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Menu item name. Must be unique.
|
|
17
|
+
*/
|
|
18
|
+
name: string;
|
|
19
|
+
/**
|
|
20
|
+
* Menu item handler function
|
|
21
|
+
*/
|
|
22
|
+
handler?: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Menu item icon, plain HTML string
|
|
25
|
+
*/
|
|
26
|
+
icon?: string;
|
|
27
|
+
};
|
|
3
28
|
/**
|
|
4
29
|
* Context menu plugin settings
|
|
5
30
|
* @beta
|
|
6
31
|
*/
|
|
7
32
|
export interface ContextMenuPluginSettings {
|
|
8
|
-
|
|
9
|
-
url?: string;
|
|
10
|
-
preventShowContextMenu?: boolean;
|
|
33
|
+
options?: MenuOption[];
|
|
11
34
|
}
|
|
12
35
|
/**
|
|
13
36
|
* `PLUGIN` that displays a small context menu when clicked on the player container.
|
|
14
37
|
* @beta
|
|
15
38
|
* @remarks
|
|
16
39
|
* Configuration options - {@link ContextMenuPluginSettings}
|
|
40
|
+
*
|
|
41
|
+
* Should not be used together with {@link ClickToPause} plugin
|
|
17
42
|
*/
|
|
18
43
|
export declare class ContextMenu extends UIContainerPlugin {
|
|
19
|
-
private
|
|
20
|
-
private _url;
|
|
21
|
-
private menuOptions;
|
|
44
|
+
private open;
|
|
22
45
|
/**
|
|
23
46
|
* @internal
|
|
24
47
|
*/
|
|
@@ -36,14 +59,11 @@ export declare class ContextMenu extends UIContainerPlugin {
|
|
|
36
59
|
class: string;
|
|
37
60
|
};
|
|
38
61
|
private static readonly template;
|
|
39
|
-
private get label();
|
|
40
|
-
private get url();
|
|
41
|
-
private get exposeVersion();
|
|
42
62
|
/**
|
|
43
63
|
* @internal
|
|
44
64
|
*/
|
|
45
65
|
get events(): {
|
|
46
|
-
'click [
|
|
66
|
+
'click [role="menuitem"]': string;
|
|
47
67
|
};
|
|
48
68
|
constructor(container: Container);
|
|
49
69
|
/**
|
|
@@ -54,10 +74,11 @@ export declare class ContextMenu extends UIContainerPlugin {
|
|
|
54
74
|
* @internal
|
|
55
75
|
*/
|
|
56
76
|
destroy(): import("@clappr/core").UIObject;
|
|
57
|
-
private
|
|
77
|
+
private onContainerClick;
|
|
78
|
+
private onContextMenu;
|
|
58
79
|
private show;
|
|
59
80
|
private hide;
|
|
60
|
-
private
|
|
81
|
+
private runAction;
|
|
61
82
|
/**
|
|
62
83
|
* @internal
|
|
63
84
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/plugins/context-menu/ContextMenu.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/plugins/context-menu/ContextMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAIhF,OAAO,gDAAgD,CAAA;AAGvD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;CACvB;AAID;;;;;;;GAOG;AACH,qBAAa,WAAY,SAAQ,iBAAiB;IAChD,OAAO,CAAC,IAAI,CAAQ;IAEpB;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,IAAa,UAAU;;MAEtB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAEzD;;OAEG;IACH,IAAa,MAAM;;MAIlB;gBAEW,SAAS,EAAE,SAAS;IAMhC;;OAEG;IACM,UAAU;IASnB;;OAEG;IACM,OAAO;IAKhB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,SAAS;IAiBjB;;OAEG;IACM,MAAM;IAkBf,OAAO,CAAC,eAAe,CAEtB;CACF"}
|