@gcorevideo/player 2.22.29 → 2.22.31
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/media-control/container.scss +2 -3
- package/assets/poster/poster.ejs +3 -1
- package/assets/poster/poster.scss +3 -3
- package/assets/skip-time/skip-time.ejs +4 -4
- package/assets/skip-time/style.scss +4 -4
- package/assets/style/main.scss +1 -1
- package/dist/core.js +1 -1
- package/dist/index.css +573 -574
- package/dist/index.js +225 -230
- package/dist/player.d.ts +63 -33
- package/docs/api/{player.seektime.bindevents.md → player.clapprstats.clearmetrics.md} +3 -3
- package/docs/api/player.clapprstats.md +14 -0
- package/docs/api/player.extendedevents.md +14 -0
- package/docs/api/player.md +13 -2
- package/docs/api/player.seektime.attributes.md +0 -1
- package/docs/api/player.seektime.md +6 -197
- package/docs/api/{player.seektime.render.md → player.seektimesettings.md} +7 -7
- package/docs/api/player.skiptime.md +3 -184
- package/lib/plugins/poster/Poster.d.ts +24 -14
- package/lib/plugins/poster/Poster.d.ts.map +1 -1
- package/lib/plugins/poster/Poster.js +67 -97
- package/lib/plugins/skip-time/SkipTime.d.ts +25 -11
- package/lib/plugins/skip-time/SkipTime.d.ts.map +1 -1
- package/lib/plugins/skip-time/SkipTime.js +43 -17
- package/lib/testUtils.d.ts +13 -39
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +14 -65
- package/package.json +1 -1
- package/src/plugins/poster/Poster.ts +91 -110
- package/src/plugins/poster/__tests__/Poster.test.ts +119 -0
- package/src/plugins/poster/__tests__/__snapshots__/Poster.test.ts.snap +8 -0
- package/src/plugins/skip-time/SkipTime.ts +52 -25
- package/src/plugins/source-controller/__tests__/SourceController.test.ts +1 -2
- package/src/testUtils.ts +14 -86
- package/temp/player.api.json +295 -829
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.seektime.durationshown.md +0 -14
- package/docs/api/player.seektime.getseektime.md +0 -20
- package/docs/api/player.seektime.islivestreamwithdvr.md +0 -14
- package/docs/api/player.seektime.mediacontrol.md +0 -14
- package/docs/api/player.seektime.mediacontrolcontainer.md +0 -14
- package/docs/api/player.seektime.shouldbevisible.md +0 -18
- package/docs/api/player.seektime.template.md +0 -14
- package/docs/api/player.seektime.update.md +0 -18
- package/docs/api/player.skiptime.attributes.md +0 -17
- package/docs/api/player.skiptime.bindevents.md +0 -18
- package/docs/api/player.skiptime.events.md +0 -18
- package/docs/api/player.skiptime.handlerewindclicks.md +0 -18
- package/docs/api/player.skiptime.render.md +0 -18
- package/docs/api/player.skiptime.setback.md +0 -18
- package/docs/api/player.skiptime.setforward.md +0 -18
- package/docs/api/player.skiptime.setmidclick.md +0 -18
- package/docs/api/player.skiptime.template.md +0 -14
- package/docs/api/player.skiptime.togglefullscreen.md +0 -18
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { UICorePlugin, Browser, Playback, Events, template } from '@clappr/core';
|
|
2
|
+
import { trace } from '@gcorevideo/utils';
|
|
2
3
|
import { CLAPPR_VERSION } from '../../build.js';
|
|
3
4
|
import pluginHtml from '../../../assets/skip-time/skip-time.ejs';
|
|
4
5
|
import '../../../assets/skip-time/style.scss';
|
|
6
|
+
const T = 'plugins.skip_time';
|
|
5
7
|
/**
|
|
6
|
-
* `PLUGIN` that
|
|
8
|
+
* `PLUGIN` that allows skipping time by tapping on the left or right side of the video.
|
|
7
9
|
* @beta
|
|
8
10
|
*/
|
|
9
11
|
export class SkipTime extends UICorePlugin {
|
|
@@ -16,39 +18,56 @@ export class SkipTime extends UICorePlugin {
|
|
|
16
18
|
get container() {
|
|
17
19
|
return this.core && this.core.activeContainer;
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
static template = template(pluginHtml);
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
22
25
|
get attributes() {
|
|
23
26
|
return {
|
|
24
|
-
class:
|
|
25
|
-
'data-skip-time': '',
|
|
27
|
+
class: 'mc-skip-time',
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
position = 'mid';
|
|
31
|
+
/**
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
29
34
|
get events() {
|
|
30
35
|
return {
|
|
31
|
-
'click
|
|
32
|
-
'click
|
|
33
|
-
'click
|
|
36
|
+
'click #mc-skip-left': 'setBack',
|
|
37
|
+
'click #mc-skip-mid': 'setMidClick',
|
|
38
|
+
'click #mc-skip-right': 'setForward',
|
|
34
39
|
};
|
|
35
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
36
44
|
bindEvents() {
|
|
37
45
|
this.listenTo(this.core, Events.CORE_READY, this.render);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
|
|
47
|
+
}
|
|
48
|
+
onContainerChanged() {
|
|
41
49
|
this.listenTo(this.container, Events.CONTAINER_DBLCLICK, this.handleRewindClicks);
|
|
50
|
+
this.mount();
|
|
42
51
|
}
|
|
43
52
|
setBack() {
|
|
53
|
+
trace(`${T} setBack`);
|
|
44
54
|
this.position = 'left';
|
|
45
55
|
}
|
|
46
56
|
handleRewindClicks() {
|
|
57
|
+
trace(`${T} handleRewindClicks`, {
|
|
58
|
+
position: this.position,
|
|
59
|
+
});
|
|
47
60
|
if (this.core.getPlaybackType() === Playback.LIVE &&
|
|
48
61
|
!this.container.isDvrEnabled()) {
|
|
49
62
|
this.toggleFullscreen();
|
|
50
63
|
return;
|
|
51
64
|
}
|
|
65
|
+
this.handleSkip();
|
|
66
|
+
}
|
|
67
|
+
handleSkip() {
|
|
68
|
+
trace(`${T} handleSkip`, {
|
|
69
|
+
position: this.position,
|
|
70
|
+
});
|
|
52
71
|
if (Browser.isMobile) {
|
|
53
72
|
if (this.position === 'left') {
|
|
54
73
|
const seekPos = this.container.getCurrentTime() - 10;
|
|
@@ -70,22 +89,29 @@ export class SkipTime extends UICorePlugin {
|
|
|
70
89
|
}
|
|
71
90
|
}
|
|
72
91
|
setMidClick() {
|
|
92
|
+
trace(`${T} setMidClick`);
|
|
73
93
|
this.position = 'mid';
|
|
74
94
|
}
|
|
75
95
|
setForward() {
|
|
96
|
+
trace(`${T} setForward`);
|
|
76
97
|
this.position = 'right';
|
|
77
98
|
}
|
|
78
99
|
toggleFullscreen() {
|
|
100
|
+
trace(`${T} toggleFullscreen`);
|
|
79
101
|
this.trigger(Events.MEDIACONTROL_FULLSCREEN, this.name);
|
|
80
102
|
this.container.fullscreen();
|
|
81
103
|
this.core.toggleFullscreen();
|
|
82
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
83
108
|
render() {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.core.activeContainer.$el.append(this.el);
|
|
87
|
-
}
|
|
88
|
-
this.bindEvents();
|
|
109
|
+
trace(`${T} render`);
|
|
110
|
+
this.$el.html(SkipTime.template());
|
|
89
111
|
return this;
|
|
90
112
|
}
|
|
113
|
+
mount() {
|
|
114
|
+
trace(`${T} mount`);
|
|
115
|
+
this.core.activeContainer.$el.append(this.el);
|
|
116
|
+
}
|
|
91
117
|
}
|
package/lib/testUtils.d.ts
CHANGED
|
@@ -1,39 +1,5 @@
|
|
|
1
1
|
import { UICorePlugin } from '@clappr/core';
|
|
2
2
|
import Events from 'eventemitter3';
|
|
3
|
-
/**
|
|
4
|
-
* @internal
|
|
5
|
-
* @deprecated
|
|
6
|
-
* TODO use createMockPlayback() instead
|
|
7
|
-
*/
|
|
8
|
-
export declare class _MockPlayback extends Events {
|
|
9
|
-
protected options: any;
|
|
10
|
-
readonly i18n: any;
|
|
11
|
-
protected playerError?: any | undefined;
|
|
12
|
-
constructor(options: any, i18n: any, playerError?: any | undefined);
|
|
13
|
-
get name(): string;
|
|
14
|
-
consent(): void;
|
|
15
|
-
play(): void;
|
|
16
|
-
pause(): void;
|
|
17
|
-
stop(): void;
|
|
18
|
-
destroy(): void;
|
|
19
|
-
seek(): void;
|
|
20
|
-
seekPercentage(): void;
|
|
21
|
-
getDuration(): number;
|
|
22
|
-
enterPiP(): void;
|
|
23
|
-
exitPiP(): void;
|
|
24
|
-
getPlaybackType(): string;
|
|
25
|
-
getStartTimeOffset(): number;
|
|
26
|
-
getCurrentTime(): number;
|
|
27
|
-
isHighDefinitionInUse(): boolean;
|
|
28
|
-
mute(): void;
|
|
29
|
-
unmute(): void;
|
|
30
|
-
volume(): void;
|
|
31
|
-
configure(): void;
|
|
32
|
-
attemptAutoPlay(): boolean;
|
|
33
|
-
canAutoPlay(): boolean;
|
|
34
|
-
onResize(): boolean;
|
|
35
|
-
trigger(event: string, ...args: any[]): void;
|
|
36
|
-
}
|
|
37
3
|
export declare function createMockCore(options?: Record<string, unknown>, container?: any): Events<string | symbol, any> & {
|
|
38
4
|
el: HTMLDivElement;
|
|
39
5
|
$el: any;
|
|
@@ -68,11 +34,12 @@ export declare function createMockPlayback(name?: string): Events<string | symbo
|
|
|
68
34
|
el: HTMLVideoElement;
|
|
69
35
|
dvrEnabled: boolean;
|
|
70
36
|
dvrInUse: boolean;
|
|
37
|
+
isAudioOnly: boolean;
|
|
71
38
|
levels: never[];
|
|
72
|
-
consent():
|
|
73
|
-
play():
|
|
74
|
-
pause():
|
|
75
|
-
stop():
|
|
39
|
+
consent: import("vitest").Mock<(...args: any[]) => any>;
|
|
40
|
+
play: import("vitest").Mock<(...args: any[]) => any>;
|
|
41
|
+
pause: import("vitest").Mock<(...args: any[]) => any>;
|
|
42
|
+
stop: import("vitest").Mock<(...args: any[]) => any>;
|
|
76
43
|
destroy: import("vitest").Mock<(...args: any[]) => any>;
|
|
77
44
|
seek: import("vitest").Mock<(...args: any[]) => any>;
|
|
78
45
|
seekPercentage: import("vitest").Mock<(...args: any[]) => any>;
|
|
@@ -97,13 +64,20 @@ export declare function createMockPlayback(name?: string): Events<string | symbo
|
|
|
97
64
|
export declare function createMockContainer(options?: Record<string, unknown>, playback?: any): Events<string | symbol, any> & {
|
|
98
65
|
el: any;
|
|
99
66
|
playback: any;
|
|
100
|
-
options:
|
|
67
|
+
options: {
|
|
68
|
+
[x: string]: unknown;
|
|
69
|
+
};
|
|
101
70
|
$el: any;
|
|
71
|
+
disableMediaControl: import("vitest").Mock<(...args: any[]) => any>;
|
|
72
|
+
enableMediaControl: import("vitest").Mock<(...args: any[]) => any>;
|
|
73
|
+
enterPiP: import("vitest").Mock<(...args: any[]) => any>;
|
|
74
|
+
exitPiP: import("vitest").Mock<(...args: any[]) => any>;
|
|
102
75
|
getDuration: import("vitest").Mock<(...args: any[]) => any>;
|
|
103
76
|
getPlugin: import("vitest").Mock<(...args: any[]) => any>;
|
|
104
77
|
getPlaybackType: import("vitest").Mock<(...args: any[]) => any>;
|
|
105
78
|
isDvrInUse: import("vitest").Mock<(...args: any[]) => any>;
|
|
106
79
|
isDvrEnabled: import("vitest").Mock<(...args: any[]) => any>;
|
|
80
|
+
isHighDefinitionInUse: import("vitest").Mock<(...args: any[]) => any>;
|
|
107
81
|
isPlaying: import("vitest").Mock<(...args: any[]) => any>;
|
|
108
82
|
play: import("vitest").Mock<(...args: any[]) => any>;
|
|
109
83
|
seek: import("vitest").Mock<(...args: any[]) => any>;
|
package/lib/testUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,MAAM,MAAM,eAAe,CAAA;AAGlC,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAAkC;;;;;;;;;;;;;;;;EAqB9C;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmC/C;AAED,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;;;;;;;;;;;;EA4BrC;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAe/C;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,OAe7C"}
|
package/lib/testUtils.js
CHANGED
|
@@ -1,65 +1,6 @@
|
|
|
1
|
-
import { $,
|
|
1
|
+
import { $, UICorePlugin } from '@clappr/core';
|
|
2
2
|
import Events from 'eventemitter3';
|
|
3
3
|
import { vi } from 'vitest';
|
|
4
|
-
/**
|
|
5
|
-
* @internal
|
|
6
|
-
* @deprecated
|
|
7
|
-
* TODO use createMockPlayback() instead
|
|
8
|
-
*/
|
|
9
|
-
export class _MockPlayback extends Events {
|
|
10
|
-
options;
|
|
11
|
-
i18n;
|
|
12
|
-
playerError;
|
|
13
|
-
constructor(options, i18n, playerError) {
|
|
14
|
-
super();
|
|
15
|
-
this.options = options;
|
|
16
|
-
this.i18n = i18n;
|
|
17
|
-
this.playerError = playerError;
|
|
18
|
-
}
|
|
19
|
-
get name() {
|
|
20
|
-
return 'mock';
|
|
21
|
-
}
|
|
22
|
-
consent() { }
|
|
23
|
-
play() { }
|
|
24
|
-
pause() { }
|
|
25
|
-
stop() { }
|
|
26
|
-
destroy() { }
|
|
27
|
-
seek() { }
|
|
28
|
-
seekPercentage() { }
|
|
29
|
-
getDuration() {
|
|
30
|
-
return 100;
|
|
31
|
-
}
|
|
32
|
-
enterPiP() { }
|
|
33
|
-
exitPiP() { }
|
|
34
|
-
getPlaybackType() {
|
|
35
|
-
return Playback.LIVE;
|
|
36
|
-
}
|
|
37
|
-
getStartTimeOffset() {
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
40
|
-
getCurrentTime() {
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
isHighDefinitionInUse() {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
mute() { }
|
|
47
|
-
unmute() { }
|
|
48
|
-
volume() { }
|
|
49
|
-
configure() { }
|
|
50
|
-
attemptAutoPlay() {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
canAutoPlay() {
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
onResize() {
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
trigger(event, ...args) {
|
|
60
|
-
this.emit(event, ...args);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
4
|
export function createMockCore(options = {}, container = createMockContainer(options)) {
|
|
64
5
|
const el = document.createElement('div');
|
|
65
6
|
const emitter = new Events();
|
|
@@ -101,11 +42,12 @@ export function createMockPlayback(name = 'mock') {
|
|
|
101
42
|
el: document.createElement('video'),
|
|
102
43
|
dvrEnabled: false,
|
|
103
44
|
dvrInUse: false,
|
|
45
|
+
isAudioOnly: false,
|
|
104
46
|
levels: [],
|
|
105
|
-
consent()
|
|
106
|
-
play()
|
|
107
|
-
pause()
|
|
108
|
-
stop()
|
|
47
|
+
consent: vi.fn(),
|
|
48
|
+
play: vi.fn(),
|
|
49
|
+
pause: vi.fn(),
|
|
50
|
+
stop: vi.fn(),
|
|
109
51
|
destroy: vi.fn(),
|
|
110
52
|
seek: vi.fn(),
|
|
111
53
|
seekPercentage: vi.fn(),
|
|
@@ -134,13 +76,20 @@ export function createMockContainer(options = {}, playback = createMockPlayback(
|
|
|
134
76
|
return Object.assign(emitter, {
|
|
135
77
|
el,
|
|
136
78
|
playback,
|
|
137
|
-
options
|
|
79
|
+
options: {
|
|
80
|
+
...options,
|
|
81
|
+
},
|
|
138
82
|
$el: $(el),
|
|
83
|
+
disableMediaControl: vi.fn(),
|
|
84
|
+
enableMediaControl: vi.fn(),
|
|
85
|
+
enterPiP: vi.fn(),
|
|
86
|
+
exitPiP: vi.fn(),
|
|
139
87
|
getDuration: vi.fn().mockReturnValue(0),
|
|
140
88
|
getPlugin: vi.fn(),
|
|
141
89
|
getPlaybackType: vi.fn(),
|
|
142
90
|
isDvrInUse: vi.fn().mockReturnValue(false),
|
|
143
91
|
isDvrEnabled: vi.fn().mockReturnValue(false),
|
|
92
|
+
isHighDefinitionInUse: vi.fn().mockReturnValue(false),
|
|
144
93
|
isPlaying: vi.fn().mockReturnValue(false),
|
|
145
94
|
play: vi.fn(),
|
|
146
95
|
seek: vi.fn(),
|
package/package.json
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
PlayerError,
|
|
9
9
|
UIContainerPlugin,
|
|
10
10
|
template,
|
|
11
|
-
$,
|
|
12
11
|
} from '@clappr/core'
|
|
13
12
|
import { trace } from '@gcorevideo/utils'
|
|
14
13
|
|
|
@@ -20,25 +19,38 @@ import posterHTML from '../../../assets/poster/poster.ejs'
|
|
|
20
19
|
import playIcon from '../../../assets/icons/new/play.svg'
|
|
21
20
|
import { PlaybackError } from '../../playback.types.js'
|
|
22
21
|
|
|
22
|
+
export type PosterPluginSettings = {
|
|
23
|
+
/**
|
|
24
|
+
* Custom CSS background
|
|
25
|
+
*/
|
|
26
|
+
custom?: string
|
|
27
|
+
/**
|
|
28
|
+
* Whether to show the poster image when the playback is noop (i.e., when there is no appropriate video playback engine for current media sources set or the media sources are not set at all)
|
|
29
|
+
*/
|
|
30
|
+
showForNoOp?: boolean
|
|
31
|
+
/**
|
|
32
|
+
* Poster image URL
|
|
33
|
+
*/
|
|
34
|
+
url?: string
|
|
35
|
+
/**
|
|
36
|
+
* Whether to show the poster after playback has ended @default true
|
|
37
|
+
*/
|
|
38
|
+
showOnVideoEnd?: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
23
41
|
const T = 'plugins.poster'
|
|
24
42
|
|
|
25
43
|
/**
|
|
26
44
|
* `PLUGIN` that displays a poster image in the background and a big play button on top when playback is stopped
|
|
27
45
|
* @beta
|
|
28
46
|
* @remarks
|
|
29
|
-
* When the playback is stopped, media control UI is disabled.
|
|
47
|
+
* When the playback is stopped or not yet started, the media control UI is disabled and hidden.
|
|
48
|
+
* Media control gets activated once the metadata is loaded after playback is initiated.
|
|
49
|
+
* This plugin displays a big play button on top of the poster image to allow user to start playback.
|
|
30
50
|
* Note that the poster image, if specified via the player config, will be used to update video element's poster attribute by the
|
|
31
51
|
* HTML5-video-based playback module.
|
|
32
52
|
*
|
|
33
|
-
* Configuration options
|
|
34
|
-
*
|
|
35
|
-
* - `poster.custom` - custom CSS background
|
|
36
|
-
*
|
|
37
|
-
* - `poster.showForNoOp` - whether to show the poster when the playback is not started
|
|
38
|
-
*
|
|
39
|
-
* - `poster.url` - the URL of the poster image
|
|
40
|
-
*
|
|
41
|
-
* - `poster.showOnVideoEnd` - whether to show the poster when the playback is ended
|
|
53
|
+
* Configuration options - {@link PosterPluginSettings}
|
|
42
54
|
*
|
|
43
55
|
* @example
|
|
44
56
|
* ```ts
|
|
@@ -56,14 +68,12 @@ export class Poster extends UIContainerPlugin {
|
|
|
56
68
|
|
|
57
69
|
private hasFatalError = false
|
|
58
70
|
|
|
59
|
-
private
|
|
71
|
+
private playing = false
|
|
60
72
|
|
|
61
73
|
private playRequested = false
|
|
62
74
|
|
|
63
75
|
private $playButton: ZeptoResult | null = null
|
|
64
76
|
|
|
65
|
-
private $playWrapper: ZeptoResult | null = null
|
|
66
|
-
|
|
67
77
|
/**
|
|
68
78
|
* @internal
|
|
69
79
|
*/
|
|
@@ -87,18 +97,20 @@ export class Poster extends UIContainerPlugin {
|
|
|
87
97
|
const showForNoOp = !!this.options.poster?.showForNoOp
|
|
88
98
|
return (
|
|
89
99
|
this.container.playback.name !== 'html_img' &&
|
|
90
|
-
(this.
|
|
91
|
-
showForNoOp)
|
|
100
|
+
(!this.isNoOp || showForNoOp)
|
|
92
101
|
)
|
|
93
102
|
}
|
|
94
103
|
|
|
104
|
+
private get isNoOp() {
|
|
105
|
+
return this.container.playback.getPlaybackType() === Playback.NO_OP
|
|
106
|
+
}
|
|
107
|
+
|
|
95
108
|
/**
|
|
96
109
|
* @internal
|
|
97
110
|
*/
|
|
98
111
|
override get attributes() {
|
|
99
112
|
return {
|
|
100
113
|
class: 'player-poster',
|
|
101
|
-
'data-poster': '',
|
|
102
114
|
}
|
|
103
115
|
}
|
|
104
116
|
|
|
@@ -111,10 +123,6 @@ export class Poster extends UIContainerPlugin {
|
|
|
111
123
|
}
|
|
112
124
|
}
|
|
113
125
|
|
|
114
|
-
private get showOnVideoEnd() {
|
|
115
|
-
return this.options.poster?.showOnVideoEnd !== false
|
|
116
|
-
}
|
|
117
|
-
|
|
118
126
|
/**
|
|
119
127
|
* @internal
|
|
120
128
|
*/
|
|
@@ -127,20 +135,27 @@ export class Poster extends UIContainerPlugin {
|
|
|
127
135
|
Events.CONTAINER_STATE_BUFFERFULL,
|
|
128
136
|
this.update,
|
|
129
137
|
)
|
|
130
|
-
this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.
|
|
138
|
+
this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.update)
|
|
131
139
|
this.listenTo(this.container, Events.CONTAINER_ERROR, this.onError)
|
|
132
|
-
this
|
|
140
|
+
// TODO check if this event is always accompanied with the CONTAINER_STOP
|
|
141
|
+
if (this.options.poster?.showOnVideoEnd !== false) {
|
|
133
142
|
this.listenTo(this.container, Events.CONTAINER_ENDED, this.onStop)
|
|
143
|
+
}
|
|
134
144
|
this.listenTo(this.container, Events.CONTAINER_READY, this.render)
|
|
135
|
-
this.listenTo(
|
|
145
|
+
this.listenTo(
|
|
146
|
+
this.container.playback,
|
|
147
|
+
Events.PLAYBACK_PLAY_INTENT,
|
|
148
|
+
this.onPlayIntent,
|
|
149
|
+
)
|
|
136
150
|
}
|
|
137
151
|
|
|
138
152
|
/**
|
|
139
153
|
* Reenables earlier disabled plugin
|
|
140
154
|
*/
|
|
141
155
|
override enable() {
|
|
156
|
+
trace(`${T} enable`)
|
|
142
157
|
super.enable()
|
|
143
|
-
this.
|
|
158
|
+
this.playing = this.container.playback.isPlaying()
|
|
144
159
|
this.update()
|
|
145
160
|
}
|
|
146
161
|
|
|
@@ -149,7 +164,7 @@ export class Poster extends UIContainerPlugin {
|
|
|
149
164
|
*/
|
|
150
165
|
override disable() {
|
|
151
166
|
trace(`${T} disable`)
|
|
152
|
-
this.
|
|
167
|
+
this.playing = false
|
|
153
168
|
this.playRequested = false
|
|
154
169
|
super.disable()
|
|
155
170
|
}
|
|
@@ -159,19 +174,16 @@ export class Poster extends UIContainerPlugin {
|
|
|
159
174
|
error,
|
|
160
175
|
enabled: this.enabled,
|
|
161
176
|
})
|
|
162
|
-
this.hasFatalError = error.level === PlayerError.Levels.FATAL
|
|
163
|
-
|
|
164
177
|
if (this.hasFatalError) {
|
|
165
|
-
|
|
166
|
-
if (!this.playRequested) {
|
|
167
|
-
this.showPlayButton()
|
|
168
|
-
}
|
|
178
|
+
return
|
|
169
179
|
}
|
|
180
|
+
this.hasFatalError = error.level === PlayerError.Levels.FATAL
|
|
181
|
+
// this.hasFatalError is reset on container recreate
|
|
170
182
|
}
|
|
171
183
|
|
|
172
184
|
private onPlay() {
|
|
173
185
|
trace(`${T} onPlay`)
|
|
174
|
-
this.
|
|
186
|
+
this.playing = true
|
|
175
187
|
this.playRequested = false
|
|
176
188
|
this.update()
|
|
177
189
|
}
|
|
@@ -183,24 +195,23 @@ export class Poster extends UIContainerPlugin {
|
|
|
183
195
|
}
|
|
184
196
|
|
|
185
197
|
private onStop() {
|
|
186
|
-
trace(`${T} onStop
|
|
187
|
-
|
|
188
|
-
})
|
|
189
|
-
this.hasStartedPlaying = false
|
|
198
|
+
trace(`${T} onStop`)
|
|
199
|
+
this.playing = false
|
|
190
200
|
this.playRequested = false
|
|
191
201
|
this.update()
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
private updatePlayButton(
|
|
195
|
-
trace(`${T} updatePlayButton
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
+
private updatePlayButton() {
|
|
205
|
+
trace(`${T} updatePlayButton`)
|
|
206
|
+
const show =
|
|
207
|
+
!this.isNoOp &&
|
|
208
|
+
!(this.options.chromeless && !this.options.allowUserInteraction) &&
|
|
209
|
+
!this.playRequested &&
|
|
210
|
+
!this.playing &&
|
|
211
|
+
!this.container.buffering &&
|
|
212
|
+
!this.hasFatalError &&
|
|
213
|
+
!this.options.disableMediaControl
|
|
214
|
+
if (show) {
|
|
204
215
|
this.showPlayButton()
|
|
205
216
|
} else {
|
|
206
217
|
this.hidePlayButton()
|
|
@@ -208,40 +219,31 @@ export class Poster extends UIContainerPlugin {
|
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
private showPlayButton() {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
if (this.hasFatalError && !this.options.disableErrorScreen) {
|
|
215
|
-
return
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
this.$playButton?.show()
|
|
222
|
+
trace(`${T} showPlayButton`)
|
|
223
|
+
this.$el.find('#poster-play').show()
|
|
219
224
|
this.$el.addClass('clickable')
|
|
220
225
|
this.container.$el.addClass('container-with-poster-clickable')
|
|
221
226
|
}
|
|
222
227
|
|
|
223
228
|
private hidePlayButton() {
|
|
224
|
-
|
|
229
|
+
trace(`${T} hidePlayButton`)
|
|
230
|
+
this.$el.find('#poster-play').hide()
|
|
225
231
|
this.$el.removeClass('clickable')
|
|
226
232
|
}
|
|
227
233
|
|
|
228
|
-
private clicked() {
|
|
229
|
-
trace(`${T} clicked
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
+
private clicked(e: MouseEvent) {
|
|
235
|
+
trace(`${T} clicked`)
|
|
236
|
+
e.preventDefault()
|
|
237
|
+
e.stopPropagation()
|
|
238
|
+
if (this.options.chromeless && !this.options.allowUserInteraction) {
|
|
239
|
+
return
|
|
240
|
+
}
|
|
234
241
|
// Let "click_to_pause" plugin handle click event if media has started playing
|
|
235
|
-
if (!this.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
this.container.playback.consent()
|
|
240
|
-
this.container.playback.play()
|
|
241
|
-
}
|
|
242
|
+
if (!this.playing) {
|
|
243
|
+
this.playRequested = true
|
|
244
|
+
this.update()
|
|
245
|
+
this.container.play()
|
|
242
246
|
}
|
|
243
|
-
|
|
244
|
-
return false
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
private shouldHideOnPlay() {
|
|
@@ -250,27 +252,15 @@ export class Poster extends UIContainerPlugin {
|
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
private update() {
|
|
253
|
-
trace(`${T} update
|
|
254
|
-
shouldRender: this.shouldRender,
|
|
255
|
-
})
|
|
256
|
-
if (!this.shouldRender) {
|
|
257
|
-
return
|
|
258
|
-
}
|
|
255
|
+
trace(`${T} update`)
|
|
259
256
|
|
|
260
|
-
|
|
261
|
-
!this.playRequested &&
|
|
262
|
-
!this.hasStartedPlaying &&
|
|
263
|
-
!this.container.buffering
|
|
264
|
-
|
|
265
|
-
this.updatePlayButton(showPlayButton)
|
|
257
|
+
this.updatePlayButton()
|
|
266
258
|
this.updatePoster()
|
|
267
259
|
}
|
|
268
260
|
|
|
269
261
|
private updatePoster() {
|
|
270
|
-
trace(`${T} updatePoster
|
|
271
|
-
|
|
272
|
-
})
|
|
273
|
-
if (!this.hasStartedPlaying) {
|
|
262
|
+
trace(`${T} updatePoster`)
|
|
263
|
+
if (!this.playing) {
|
|
274
264
|
this.showPoster()
|
|
275
265
|
} else {
|
|
276
266
|
this.hidePoster()
|
|
@@ -283,9 +273,7 @@ export class Poster extends UIContainerPlugin {
|
|
|
283
273
|
}
|
|
284
274
|
|
|
285
275
|
private hidePoster() {
|
|
286
|
-
trace(`${T} hidePoster
|
|
287
|
-
shouldHideOnPlay: this.shouldHideOnPlay(),
|
|
288
|
-
})
|
|
276
|
+
trace(`${T} hidePoster`)
|
|
289
277
|
if (!this.options.disableMediaControl) {
|
|
290
278
|
this.container.enableMediaControl()
|
|
291
279
|
}
|
|
@@ -304,34 +292,27 @@ export class Poster extends UIContainerPlugin {
|
|
|
304
292
|
|
|
305
293
|
this.$el.html(Poster.template())
|
|
306
294
|
|
|
307
|
-
const
|
|
308
|
-
this.options.poster && this.options.poster.custom === undefined
|
|
295
|
+
const isCustomPoster = this.options.poster?.custom !== undefined
|
|
309
296
|
|
|
310
|
-
if (
|
|
311
|
-
const posterUrl = this.options.poster.url || this.options.poster
|
|
312
|
-
|
|
313
|
-
this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
|
|
314
|
-
} else if (this.options.poster) {
|
|
297
|
+
if (isCustomPoster) {
|
|
315
298
|
this.$el.css({ background: this.options.poster.custom })
|
|
299
|
+
} else {
|
|
300
|
+
const posterUrl =
|
|
301
|
+
typeof this.options.poster === 'string'
|
|
302
|
+
? this.options.poster
|
|
303
|
+
: this.options.poster?.url
|
|
304
|
+
if (posterUrl) {
|
|
305
|
+
this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
|
|
306
|
+
}
|
|
316
307
|
}
|
|
317
308
|
|
|
318
309
|
this.container.$el.removeClass('container-with-poster-clickable')
|
|
319
310
|
this.container.$el.append(this.el)
|
|
320
|
-
this.$
|
|
321
|
-
this.$playWrapper.addClass('control-need-disable')
|
|
322
|
-
this.$playButton = $(
|
|
323
|
-
"<div class='circle-poster gcore-skin-button-color gcore-skin-border-color'></div>",
|
|
324
|
-
)
|
|
325
|
-
this.$playWrapper.append(this.$playButton)
|
|
326
|
-
this.$playButton.append(playIcon)
|
|
311
|
+
this.$el.find('#poster-play').append(playIcon)
|
|
327
312
|
|
|
328
|
-
if (this.options.autoPlay) {
|
|
329
|
-
this.$
|
|
313
|
+
if (this.options.autoPlay || this.isNoOp) {
|
|
314
|
+
this.$el.find('#poster-play').hide()
|
|
330
315
|
}
|
|
331
|
-
this.$playButton.addClass('poster-icon')
|
|
332
|
-
this.$playButton.attr('data-poster', '')
|
|
333
|
-
|
|
334
|
-
this.update()
|
|
335
316
|
|
|
336
317
|
return this
|
|
337
318
|
}
|