@gcorevideo/player 2.24.0 → 2.24.2
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/bottom-gear/gear-sub-menu.scss +1 -0
- package/dist/core.js +1 -1
- package/dist/index.css +761 -760
- package/dist/index.js +70 -76
- package/dist/player.d.ts +46 -1
- package/docs/api/player.cmcdconfig._constructor_.md +50 -0
- package/docs/api/player.cmcdconfig.bindevents.md +19 -0
- package/docs/api/player.cmcdconfig.exportids.md +21 -0
- package/docs/api/player.cmcdconfig.md +191 -0
- package/docs/api/player.cmcdconfig.name.md +15 -0
- package/docs/api/player.cmcdconfig.supportedversion.md +14 -0
- package/docs/api/player.cmcdconfig.version.md +14 -0
- package/docs/api/player.cmcdconfigpluginsettings.md +18 -0
- package/docs/api/player.md +22 -0
- package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -0
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +17 -17
- package/lib/plugins/cmcd-config/CmcdConfig.d.ts +8 -8
- package/lib/plugins/cmcd-config/CmcdConfig.d.ts.map +1 -1
- package/lib/plugins/cmcd-config/CmcdConfig.js +43 -47
- package/lib/plugins/cmcd-config/utils.d.ts +0 -1
- package/lib/plugins/cmcd-config/utils.d.ts.map +1 -1
- package/lib/plugins/cmcd-config/utils.js +0 -9
- package/lib/plugins/media-control/MediaControl.d.ts +7 -0
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +14 -5
- package/lib/testUtils.d.ts +1 -0
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +3 -0
- package/package.json +1 -1
- package/src/plugins/bottom-gear/BottomGear.ts +40 -28
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +34 -7
- package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +5 -2
- package/src/plugins/cmcd-config/CmcdConfig.ts +57 -57
- package/src/plugins/cmcd-config/__tests__/CmcdConfig.test.ts +96 -84
- package/src/plugins/cmcd-config/utils.ts +0 -10
- package/src/plugins/media-control/MediaControl.ts +18 -6
- package/src/testUtils.ts +3 -0
- package/temp/player.api.json +243 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -31,6 +31,15 @@ describe('BottomGear', () => {
|
|
|
31
31
|
bottomGear.on(GearEvents.RENDERED, onGearRendered, null)
|
|
32
32
|
core.emit(Events.CORE_READY)
|
|
33
33
|
bottomGear.addItem('test', null).html('<button>test</button>')
|
|
34
|
+
const $moreOptions = $(
|
|
35
|
+
`<div>
|
|
36
|
+
<button id="more-options-back">< back</button>
|
|
37
|
+
<ul class="gear-sub-menu" id="more-options"><li>Item</li><li>Item</li><li>Item</li></ul>
|
|
38
|
+
</div>`,
|
|
39
|
+
)
|
|
40
|
+
bottomGear
|
|
41
|
+
.addItem('more', $moreOptions)
|
|
42
|
+
.html('<button id="more-button">more options</button>')
|
|
34
43
|
})
|
|
35
44
|
it('should render', () => {
|
|
36
45
|
expect(bottomGear.el.innerHTML).toMatchSnapshot()
|
|
@@ -99,6 +108,26 @@ describe('BottomGear', () => {
|
|
|
99
108
|
)
|
|
100
109
|
})
|
|
101
110
|
})
|
|
111
|
+
describe('when submenu is open', () => {
|
|
112
|
+
beforeEach(async () => {
|
|
113
|
+
mediaControl.getAvailableHeight.mockReturnValue(198)
|
|
114
|
+
bottomGear.$el.find('#gear-button').click()
|
|
115
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
116
|
+
bottomGear.$el.find('#more-button').click()
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
118
|
+
})
|
|
119
|
+
it('should show submenu', () => {
|
|
120
|
+
expect(
|
|
121
|
+
bottomGear.$el.find('#more-options').parent().css('display'),
|
|
122
|
+
).not.toBe('none')
|
|
123
|
+
})
|
|
124
|
+
it('should align nicely within container', () => {
|
|
125
|
+
const submenu = bottomGear.$el.find('#more-options')
|
|
126
|
+
const wrapper = submenu.parent()
|
|
127
|
+
expect(wrapper.css('max-height')).toBe('174px') // available height minus vertical margins
|
|
128
|
+
expect(submenu.css('max-height')).toBe('130px') // wrapper height minus backlink height
|
|
129
|
+
})
|
|
130
|
+
})
|
|
102
131
|
})
|
|
103
132
|
describe('when there are no items', () => {
|
|
104
133
|
beforeEach(() => {
|
|
@@ -128,9 +157,9 @@ describe('BottomGear', () => {
|
|
|
128
157
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
129
158
|
})
|
|
130
159
|
it('should collapse the gear menu', () => {
|
|
131
|
-
expect(
|
|
132
|
-
'
|
|
133
|
-
)
|
|
160
|
+
expect(
|
|
161
|
+
bottomGear.$el.find('#gear-options-wrapper').css('display'),
|
|
162
|
+
).toBe('none')
|
|
134
163
|
expect(bottomGear.$el.find('#gear-button').attr('aria-expanded')).toBe(
|
|
135
164
|
'false',
|
|
136
165
|
)
|
|
@@ -140,14 +169,12 @@ describe('BottomGear', () => {
|
|
|
140
169
|
describe('when submenu is open', () => {
|
|
141
170
|
beforeEach(async () => {
|
|
142
171
|
// bottomGear.$el.find('#test-submenu').click()
|
|
143
|
-
bottomGear.$el.find('#test-options').show()
|
|
172
|
+
bottomGear.$el.find('#test-options').show() // as if it was clicked
|
|
144
173
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
145
174
|
mediaControl.container.trigger(Events.CONTAINER_CLICK)
|
|
146
175
|
})
|
|
147
176
|
it('should collapse it as well', () => {
|
|
148
|
-
expect(bottomGear.$el.find('#test-options').css('display')).toBe(
|
|
149
|
-
'none',
|
|
150
|
-
)
|
|
177
|
+
expect(bottomGear.$el.find('#test-options').css('display')).toBe('none')
|
|
151
178
|
expect(bottomGear.$el.find('#gear-options').css('display')).not.toBe(
|
|
152
179
|
'none',
|
|
153
180
|
)
|
|
@@ -5,7 +5,10 @@ exports[`BottomGear > basically > should render 1`] = `
|
|
|
5
5
|
/assets/icons/new/gear.svg
|
|
6
6
|
</button>
|
|
7
7
|
<div class="gear-wrapper gcore-skin-bg-color" id="gear-options-wrapper" style="display: none;">
|
|
8
|
-
<ul class="gear-options-list" id="gear-options" role="menu"><li data-test=""><button>test</button></li></ul>
|
|
9
|
-
|
|
8
|
+
<ul class="gear-options-list" id="gear-options" role="menu"><li data-test=""><button>test</button></li><li data-more=""><button id="more-button">more options</button></li></ul>
|
|
9
|
+
<div class="gear-sub-menu-wrapper" style="display: none;">
|
|
10
|
+
<button id="more-options-back">< back</button>
|
|
11
|
+
<ul class="gear-sub-menu" id="more-options"><li>Item</li><li>Item</li><li>Item</li></ul>
|
|
12
|
+
</div></div>
|
|
10
13
|
"
|
|
11
14
|
`;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Core,
|
|
3
|
-
CorePlugin,
|
|
4
|
-
Events,
|
|
5
|
-
} from '@clappr/core'
|
|
1
|
+
import { $, Container, Core, CorePlugin, Events } from '@clappr/core'
|
|
6
2
|
|
|
7
|
-
import {
|
|
3
|
+
// import { trace } from '@gcorevideo/utils'
|
|
4
|
+
|
|
5
|
+
import { generateSessionId } from './utils'
|
|
6
|
+
import { CLAPPR_VERSION } from '../../build.js'
|
|
7
|
+
import { CoreOptions } from 'src/internal.types'
|
|
8
8
|
|
|
9
9
|
const CMCD_KEYS = [
|
|
10
10
|
'br',
|
|
@@ -36,12 +36,14 @@ export type CmcdConfigPluginSettings = {
|
|
|
36
36
|
*/
|
|
37
37
|
sessionId: string
|
|
38
38
|
/**
|
|
39
|
-
* Content ID,
|
|
40
|
-
* If ommitted,
|
|
39
|
+
* Content ID,
|
|
40
|
+
* If ommitted, the pathname part of the first source URL will be used
|
|
41
41
|
*/
|
|
42
|
-
contentId?: string
|
|
42
|
+
contentId?: string
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// const T = 'plugins.cmcd'
|
|
46
|
+
|
|
45
47
|
/**
|
|
46
48
|
* A `PLUGIN` that configures CMCD for playback
|
|
47
49
|
* @beta
|
|
@@ -61,63 +63,73 @@ export class CmcdConfig extends CorePlugin {
|
|
|
61
63
|
return 'cmcd'
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
get version() {
|
|
67
|
+
return '0.1.0'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get supportedVersion() {
|
|
71
|
+
return CLAPPR_VERSION
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
constructor(core: Core) {
|
|
65
75
|
super(core)
|
|
66
76
|
this.sid = this.options.cmcd?.sessionId ?? generateSessionId()
|
|
77
|
+
this.cid = this.options.cmcd?.contentId ?? this.generateContentId()
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
/**
|
|
70
81
|
* @inheritdocs
|
|
71
82
|
*/
|
|
72
83
|
override bindEvents() {
|
|
73
|
-
this.listenTo(this.core, Events.
|
|
74
|
-
this.updateSettings(),
|
|
84
|
+
this.listenTo(this.core, Events.CORE_CONTAINERS_CREATED, () =>
|
|
85
|
+
this.updateSettings(this.core.containers[0]),
|
|
75
86
|
)
|
|
76
87
|
}
|
|
77
88
|
|
|
78
|
-
|
|
89
|
+
exportIds(): { sid: string; cid: string } {
|
|
79
90
|
return {
|
|
80
91
|
sid: this.sid,
|
|
81
|
-
cid:
|
|
92
|
+
cid: this.cid,
|
|
82
93
|
}
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
private updateSettings() {
|
|
86
|
-
switch (
|
|
96
|
+
private async updateSettings(container: Container) {
|
|
97
|
+
switch (container.playback.name) {
|
|
87
98
|
case 'dash':
|
|
88
|
-
|
|
99
|
+
$.extend(true, container.playback.options, {
|
|
100
|
+
dash: {
|
|
101
|
+
cmcd: {
|
|
102
|
+
enabled: true,
|
|
103
|
+
enabledKeys: CMCD_KEYS,
|
|
104
|
+
sid: this.sid,
|
|
105
|
+
cid: this.cid,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
})
|
|
89
109
|
break
|
|
90
110
|
case 'hls':
|
|
91
|
-
|
|
111
|
+
$.extend(true, container.playback.options, {
|
|
112
|
+
playback: {
|
|
113
|
+
hlsjsConfig: {
|
|
114
|
+
cmcd: {
|
|
115
|
+
includeKeys: CMCD_KEYS,
|
|
116
|
+
sessionId: this.sid,
|
|
117
|
+
contentId: this.cid,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
})
|
|
92
122
|
break
|
|
93
123
|
}
|
|
94
124
|
}
|
|
95
125
|
|
|
96
|
-
private
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
dash: {
|
|
102
|
-
...(options.dash ?? {}),
|
|
103
|
-
cmcd: {
|
|
104
|
-
enabled: true,
|
|
105
|
-
enabledKeys: CMCD_KEYS,
|
|
106
|
-
sid,
|
|
107
|
-
cid,
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private async updateHlsjsSettings() {
|
|
114
|
-
const { cid, sid } = await this.getIds()
|
|
115
|
-
const options = this.core.activePlayback.options
|
|
116
|
-
this.core.activePlayback.options = {
|
|
117
|
-
...options,
|
|
126
|
+
private updateHlsjsSettings(
|
|
127
|
+
options: CoreOptions,
|
|
128
|
+
{ cid, sid }: { cid: string; sid: string },
|
|
129
|
+
) {
|
|
130
|
+
$.extend(true, options, {
|
|
118
131
|
playback: {
|
|
119
132
|
hlsjsConfig: {
|
|
120
|
-
...(options.playback?.hlsjsConfig ?? {}),
|
|
121
133
|
cmcd: {
|
|
122
134
|
includeKeys: CMCD_KEYS,
|
|
123
135
|
sessionId: sid,
|
|
@@ -125,24 +137,12 @@ export class CmcdConfig extends CorePlugin {
|
|
|
125
137
|
},
|
|
126
138
|
},
|
|
127
139
|
},
|
|
128
|
-
}
|
|
140
|
+
})
|
|
129
141
|
}
|
|
130
142
|
|
|
131
|
-
private
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
return this.cid
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
private async evalContentId(): Promise<string> {
|
|
139
|
-
if (!this.core.activeContainer.options.cmcd?.contentId) {
|
|
140
|
-
return generateContentId(this.core.activePlayback.options.src)
|
|
141
|
-
}
|
|
142
|
-
const contentId = this.core.activeContainer.options.cmcd.contentId
|
|
143
|
-
if (typeof contentId === 'string') {
|
|
144
|
-
return contentId
|
|
145
|
-
}
|
|
146
|
-
return Promise.resolve(contentId(this.core.activePlayback.options.src))
|
|
143
|
+
private generateContentId() {
|
|
144
|
+
return new URL(
|
|
145
|
+
this.core.options.source ?? this.core.options.sources[0].source,
|
|
146
|
+
).pathname.slice(0, 64)
|
|
147
147
|
}
|
|
148
148
|
}
|
|
@@ -3,13 +3,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
3
3
|
import { CmcdConfig } from '../CmcdConfig'
|
|
4
4
|
import { createMockCore } from '../../../testUtils'
|
|
5
5
|
import { Events } from '@clappr/core'
|
|
6
|
-
import { generateContentId } from '../utils'
|
|
7
|
-
|
|
8
|
-
import { createHash } from 'node:crypto'
|
|
9
6
|
|
|
10
7
|
vi.mock('../utils', () => ({
|
|
11
8
|
generateSessionId: vi.fn().mockReturnValue('123'),
|
|
12
|
-
generateContentId: vi.fn().mockResolvedValue('deadbeef'),
|
|
13
9
|
}))
|
|
14
10
|
|
|
15
11
|
const CMCD_KEYS = [
|
|
@@ -38,69 +34,78 @@ describe('CmcdConfig', () => {
|
|
|
38
34
|
let plugin: CmcdConfig
|
|
39
35
|
describe('basically', () => {
|
|
40
36
|
beforeEach(() => {
|
|
41
|
-
core = createMockCore({
|
|
37
|
+
core = createMockCore({
|
|
38
|
+
sources: [
|
|
39
|
+
{
|
|
40
|
+
source: 'https://zulu.com/123.mpd',
|
|
41
|
+
mimeType: 'application/dash+xml',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
})
|
|
42
45
|
})
|
|
43
|
-
describe('when
|
|
46
|
+
describe('when container is created', () => {
|
|
44
47
|
describe('dash.js', () => {
|
|
45
48
|
beforeEach(async () => {
|
|
46
|
-
core.
|
|
47
|
-
core.activeContainer.playback.options.src = 'https://123.mpd'
|
|
49
|
+
core.containers[0].playback.name = 'dash'
|
|
48
50
|
plugin = new CmcdConfig(core)
|
|
49
|
-
core.trigger(Events.
|
|
50
|
-
await new Promise(resolve => setTimeout(resolve, 0))
|
|
51
|
+
core.trigger(Events.CORE_CONTAINERS_CREATED)
|
|
52
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
51
53
|
})
|
|
52
54
|
it('should update DASH.js CMCD settings', () => {
|
|
53
|
-
expect(core.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
56
|
+
expect.objectContaining({
|
|
57
|
+
dash: expect.objectContaining({
|
|
58
|
+
cmcd: expect.objectContaining({
|
|
59
|
+
enabled: true,
|
|
60
|
+
enabledKeys: CMCD_KEYS,
|
|
61
|
+
}),
|
|
62
|
+
}),
|
|
63
|
+
}),
|
|
64
|
+
)
|
|
61
65
|
})
|
|
62
66
|
it('should generate unique session ID', () => {
|
|
63
|
-
expect(core.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
68
|
+
expect.objectContaining({
|
|
69
|
+
dash: expect.objectContaining({
|
|
70
|
+
cmcd: expect.objectContaining({
|
|
71
|
+
sid: '123',
|
|
72
|
+
}),
|
|
73
|
+
}),
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
70
76
|
})
|
|
71
77
|
it('should compute content ID from source URL', () => {
|
|
72
|
-
expect(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
79
|
+
expect.objectContaining({
|
|
80
|
+
dash: expect.objectContaining({
|
|
81
|
+
cmcd: expect.objectContaining({
|
|
82
|
+
cid: '/123.mpd',
|
|
83
|
+
}),
|
|
84
|
+
}),
|
|
85
|
+
}),
|
|
86
|
+
)
|
|
80
87
|
})
|
|
81
88
|
})
|
|
82
89
|
describe('hls.js', () => {
|
|
83
90
|
beforeEach(async () => {
|
|
84
|
-
core.
|
|
85
|
-
core.activeContainer.playback.options.src = 'https://123.m3u8'
|
|
91
|
+
core.containers[0].playback.name = 'hls'
|
|
86
92
|
plugin = new CmcdConfig(core)
|
|
87
|
-
|
|
88
|
-
core.trigger(Events.CORE_ACTIVE_CONTAINER_CHANGED)
|
|
89
|
-
await new Promise(resolve => setTimeout(resolve, 0))
|
|
93
|
+
core.trigger(Events.CORE_CONTAINERS_CREATED)
|
|
90
94
|
})
|
|
91
95
|
it('should update HLS.js CMCD settings', () => {
|
|
92
|
-
expect(core.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
97
|
+
expect.objectContaining({
|
|
98
|
+
playback: expect.objectContaining({
|
|
99
|
+
hlsjsConfig: expect.objectContaining({
|
|
100
|
+
cmcd: expect.objectContaining({
|
|
101
|
+
includeKeys: CMCD_KEYS,
|
|
102
|
+
contentId: '/123.mpd',
|
|
103
|
+
sessionId: '123',
|
|
104
|
+
}),
|
|
105
|
+
}),
|
|
106
|
+
}),
|
|
107
|
+
}),
|
|
108
|
+
)
|
|
104
109
|
})
|
|
105
110
|
})
|
|
106
111
|
})
|
|
@@ -109,54 +114,61 @@ describe('CmcdConfig', () => {
|
|
|
109
114
|
beforeEach(async () => {
|
|
110
115
|
core = createMockCore({
|
|
111
116
|
cmcd: {
|
|
112
|
-
contentId:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
h.end()
|
|
122
|
-
}),
|
|
123
|
-
}
|
|
117
|
+
contentId:
|
|
118
|
+
'e287ea99b57c09b7a185aaaf36e075f2c0b346ce90aeced72976b1732678a8c6',
|
|
119
|
+
},
|
|
120
|
+
sources: [
|
|
121
|
+
{
|
|
122
|
+
source: 'https://zulu.com/123.mpd',
|
|
123
|
+
mimeType: 'application/dash+xml',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
124
126
|
})
|
|
125
|
-
core.
|
|
126
|
-
core.
|
|
127
|
+
core.containers[0].playback.name = 'dash'
|
|
128
|
+
core.containers[0].playback.options.src = 'https://123.mpd'
|
|
127
129
|
plugin = new CmcdConfig(core)
|
|
128
|
-
core.trigger(Events.
|
|
129
|
-
await new Promise(resolve => setTimeout(resolve, 0))
|
|
130
|
+
core.trigger(Events.CORE_CONTAINERS_CREATED)
|
|
131
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
130
132
|
})
|
|
131
133
|
it('should use custom content ID', () => {
|
|
132
|
-
expect(core.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
135
|
+
expect.objectContaining({
|
|
136
|
+
dash: expect.objectContaining({
|
|
137
|
+
cmcd: expect.objectContaining({
|
|
138
|
+
cid: 'e287ea99b57c09b7a185aaaf36e075f2c0b346ce90aeced72976b1732678a8c6',
|
|
139
|
+
}),
|
|
140
|
+
}),
|
|
141
|
+
}),
|
|
142
|
+
)
|
|
139
143
|
})
|
|
140
144
|
})
|
|
141
145
|
describe('custom session ID', () => {
|
|
142
146
|
beforeEach(async () => {
|
|
143
147
|
core = createMockCore({
|
|
144
148
|
cmcd: { sessionId: '456' },
|
|
149
|
+
sources: [
|
|
150
|
+
{
|
|
151
|
+
source: 'https://zulu.com/123.mpd',
|
|
152
|
+
mimeType: 'application/dash+xml',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
145
155
|
})
|
|
146
|
-
core.
|
|
147
|
-
core.
|
|
156
|
+
core.containers[0].playback.name = 'dash'
|
|
157
|
+
core.containers[0].playback.options.src = 'https://123.mpd'
|
|
148
158
|
plugin = new CmcdConfig(core)
|
|
149
|
-
core.trigger(Events.
|
|
150
|
-
await new Promise(resolve => setTimeout(resolve, 0))
|
|
159
|
+
core.trigger(Events.CORE_CONTAINERS_CREATED)
|
|
160
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
151
161
|
})
|
|
152
162
|
it('should use custom session ID', () => {
|
|
153
|
-
expect(core.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
expect(core.containers[0].playback.options).toEqual(
|
|
164
|
+
expect.objectContaining({
|
|
165
|
+
dash: expect.objectContaining({
|
|
166
|
+
cmcd: expect.objectContaining({
|
|
167
|
+
sid: '456',
|
|
168
|
+
}),
|
|
169
|
+
}),
|
|
170
|
+
}),
|
|
171
|
+
)
|
|
160
172
|
})
|
|
161
173
|
})
|
|
162
174
|
})
|
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
export function generateSessionId(): string {
|
|
2
2
|
return window.crypto.randomUUID()
|
|
3
3
|
}
|
|
4
|
-
|
|
5
|
-
export function generateContentId(sourceUrl: string): Promise<string> {
|
|
6
|
-
return window.crypto.subtle.digest('SHA-1', new TextEncoder().encode(sourceUrl))
|
|
7
|
-
.then(buffer => {
|
|
8
|
-
const hex = Array.from(new Uint8Array(buffer))
|
|
9
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
|
10
|
-
.join('')
|
|
11
|
-
return hex
|
|
12
|
-
})
|
|
13
|
-
}
|
|
@@ -531,6 +531,18 @@ export class MediaControl extends UICorePlugin {
|
|
|
531
531
|
this.show()
|
|
532
532
|
}
|
|
533
533
|
|
|
534
|
+
/**
|
|
535
|
+
*
|
|
536
|
+
* @returns Vertical space available to render something on top of the container.
|
|
537
|
+
* @remarks
|
|
538
|
+
* This takes into account the container height and excludes the height of the controls bar
|
|
539
|
+
*/
|
|
540
|
+
getAvailableHeight() {
|
|
541
|
+
return (
|
|
542
|
+
this.core.$el.height() - this.$el.find('.media-control-layer').height()
|
|
543
|
+
)
|
|
544
|
+
}
|
|
545
|
+
|
|
534
546
|
/**
|
|
535
547
|
* Set the initial volume, which is preserved when playback is interrupted by an advertisement
|
|
536
548
|
*/
|
|
@@ -645,12 +657,12 @@ export class MediaControl extends UICorePlugin {
|
|
|
645
657
|
}
|
|
646
658
|
|
|
647
659
|
private mousemoveOnSeekBar(event: MouseEvent) {
|
|
648
|
-
const offset =
|
|
649
|
-
(this.$seekBarContainer.offset().left ?? 0) // TODO check if the result can be negative
|
|
650
|
-
const hoverOffset =
|
|
651
|
-
|
|
652
|
-
(this.$
|
|
653
|
-
|
|
660
|
+
const offset =
|
|
661
|
+
MediaControl.getPageX(event) - (this.$seekBarContainer.offset().left ?? 0) // TODO check if the result can be negative
|
|
662
|
+
const hoverOffset = offset - (this.$seekBarHover.width() ?? 0) / 2
|
|
663
|
+
const pos = offset
|
|
664
|
+
? Math.min(1, Math.max(offset / this.$seekBarContainer.width(), 0))
|
|
665
|
+
: 0
|
|
654
666
|
if (this.settings.seekEnabled) {
|
|
655
667
|
// TODO test that it works when the element does not exist
|
|
656
668
|
this.$seekBarHover.css({ left: hoverOffset })
|
package/src/testUtils.ts
CHANGED
|
@@ -13,6 +13,7 @@ export function createMockCore(
|
|
|
13
13
|
$el: $(el),
|
|
14
14
|
activePlayback: container.playback,
|
|
15
15
|
activeContainer: container,
|
|
16
|
+
containers: [container],
|
|
16
17
|
i18n: {
|
|
17
18
|
t: vi.fn().mockImplementation((key: string) => key),
|
|
18
19
|
},
|
|
@@ -125,6 +126,8 @@ export function createMockMediaControl(core: any) {
|
|
|
125
126
|
// @ts-ignore
|
|
126
127
|
mediaControl.container = core.activeContainer
|
|
127
128
|
// @ts-ignore
|
|
129
|
+
mediaControl.getAvailableHeight = vi.fn().mockReturnValue(300)
|
|
130
|
+
// @ts-ignore
|
|
128
131
|
mediaControl.toggleElement = vi.fn()
|
|
129
132
|
vi.spyOn(mediaControl, 'trigger')
|
|
130
133
|
core.$el.append(mediaControl.$el)
|