@playkit-js/moderation 2.1.1 → 2.2.0-canary.2-223f8a4
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/CHANGELOG.md +7 -0
- package/LICENSE +5 -5
- package/README.md +105 -8
- package/dist/3758875b5327755db91c.svg +3 -0
- package/dist/4e88e84bb6cd6f386467.svg +9 -0
- package/{src/components/moderation/assets/down.svg → dist/699b282225ecacccffd9.svg} +2 -2
- package/dist/f4a8c73d84c247e719f8.svg +3 -0
- package/dist/playkit-moderation.js +1 -23
- package/dist/playkit-moderation.js.map +1 -1
- package/package.json +49 -54
- package/src/components/a11y-wrapper/a11y-wrapper.tsx +26 -0
- package/src/components/a11y-wrapper/index.ts +1 -0
- package/src/components/icons/index.ts +9 -0
- package/src/components/moderation/moderation.scss +25 -7
- package/src/components/moderation/moderation.tsx +64 -104
- package/src/components/plugin-button/plugin-button.scss +14 -14
- package/src/components/plugin-button/plugin-button.tsx +26 -3
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover/popover-menu.scss +4 -0
- package/src/components/popover/popover-menu.tsx +57 -0
- package/src/components/popover/popover.scss +30 -0
- package/src/components/popover/popover.tsx +224 -0
- package/src/contrib-services/common-types.ts +2 -0
- package/src/contrib-services/contrib-services.ts +80 -0
- package/src/contrib-services/contrib-utils.ts +16 -0
- package/src/contrib-services/events-manager.ts +59 -0
- package/src/contrib-services/floating-item-data.tsx +31 -0
- package/src/contrib-services/floating-item.tsx +116 -0
- package/src/contrib-services/floating-manager.tsx +224 -0
- package/src/contrib-services/index.ts +2 -0
- package/src/contrib-services/injected-component/index.ts +1 -0
- package/src/contrib-services/injected-component/injected-component.scss +5 -0
- package/src/contrib-services/injected-component/injected-component.tsx +58 -0
- package/src/contrib-services/kaltura-player-utils.ts +18 -0
- package/src/contrib-services/managed-component/_managed-component.scss +8 -0
- package/src/contrib-services/managed-component/index.ts +1 -0
- package/src/contrib-services/managed-component/managed-component.tsx +71 -0
- package/src/contrib-services/object-utils.ts +157 -0
- package/src/contrib-services/player-contrib-registry.ts +34 -0
- package/src/contrib-services/player-utils.ts +37 -0
- package/src/contrib-services/preset-item-data.tsx +43 -0
- package/src/contrib-services/preset-item.tsx +113 -0
- package/src/contrib-services/preset-manager.tsx +153 -0
- package/src/contrib-services/presets-utils.ts +27 -0
- package/src/contrib-services/toast/_toast.scss +93 -0
- package/src/contrib-services/toast/assets/close.svg +9 -0
- package/src/contrib-services/toast/index.ts +1 -0
- package/src/contrib-services/toast/toast.tsx +67 -0
- package/src/contrib-services/toast-manager.tsx +121 -0
- package/src/contrib-services/toasts-container/_toasts-container.scss +21 -0
- package/src/contrib-services/toasts-container/index.ts +1 -0
- package/src/contrib-services/toasts-container/toasts-container.tsx +23 -0
- package/src/contrib-services/ui-player-adapter/index.tsx +1 -0
- package/src/contrib-services/ui-player-adapter/ui-player-adapter.tsx +27 -0
- package/src/contrib-services/uuid.ts +6 -0
- package/src/global.d.ts +6 -6
- package/src/index.ts +13 -1
- package/src/moderation-plugin.scss +12 -12
- package/src/moderation-plugin.tsx +123 -160
- package/src/providers/index.ts +2 -0
- package/src/providers/report-loader.ts +69 -0
- package/src/providers/response-types/index.ts +2 -0
- package/src/providers/response-types/kaltura-moderation-flag-response.ts +13 -0
- package/src/providers/response-types/kaltura-moderation-flag.ts +51 -0
- package/src/variables.scss +4 -1
- package/src/assets/.gitkeep +0 -0
- package/src/assets/close.svg +0 -10
- package/src/assets/flag.svg +0 -6
- package/src/components/.gitkeep +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import {FloatingItem} from './floating-item';
|
|
2
|
+
import {
|
|
3
|
+
FloatingItemData,
|
|
4
|
+
FloatingItemProps,
|
|
5
|
+
FloatingPositions,
|
|
6
|
+
} from './floating-item-data';
|
|
7
|
+
import {PresetManager, PresetManagerEventTypes} from './preset-manager';
|
|
8
|
+
import {ComponentChild, h} from 'preact';
|
|
9
|
+
import {PlayerSize, VideoSize} from './common-types';
|
|
10
|
+
import {getPlayerSize, getVideoSize} from './player-utils';
|
|
11
|
+
import {ManagedComponent} from './managed-component';
|
|
12
|
+
import {PresetsUtils} from './presets-utils';
|
|
13
|
+
import {getContribConfig} from './contrib-utils';
|
|
14
|
+
|
|
15
|
+
export interface FloatingManagerOptions {
|
|
16
|
+
kalturaPlayer: KalturaPlayerTypes.Player;
|
|
17
|
+
presetManager: PresetManager;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const defaultFloatingConfig: any = {
|
|
21
|
+
presetAreasMapping: {
|
|
22
|
+
Playback: {
|
|
23
|
+
VideoArea: 'VideoArea',
|
|
24
|
+
PresetArea: 'PresetArea',
|
|
25
|
+
InteractiveArea: 'InteractiveArea',
|
|
26
|
+
},
|
|
27
|
+
Live: {
|
|
28
|
+
VideoArea: 'VideoArea',
|
|
29
|
+
PresetArea: 'PresetArea',
|
|
30
|
+
InteractiveArea: 'InteractiveArea',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const acceptableTypes = ['VideoArea', 'PresetArea', 'InteractiveArea'];
|
|
36
|
+
|
|
37
|
+
export class FloatingManager {
|
|
38
|
+
private _items: Record<FloatingPositions, FloatingItem[]> = {
|
|
39
|
+
[FloatingPositions.VideoArea]: [],
|
|
40
|
+
[FloatingPositions.InteractiveArea]: [],
|
|
41
|
+
[FloatingPositions.PresetArea]: [],
|
|
42
|
+
};
|
|
43
|
+
private _componentRef: Record<FloatingPositions, ManagedComponent | null> = {
|
|
44
|
+
[FloatingPositions.InteractiveArea]: null,
|
|
45
|
+
[FloatingPositions.VideoArea]: null,
|
|
46
|
+
[FloatingPositions.PresetArea]: null,
|
|
47
|
+
};
|
|
48
|
+
private _cache: {
|
|
49
|
+
canvas: {
|
|
50
|
+
playerSize: PlayerSize;
|
|
51
|
+
videoSize: VideoSize;
|
|
52
|
+
};
|
|
53
|
+
} = {
|
|
54
|
+
canvas: {
|
|
55
|
+
playerSize: {width: 0, height: 0},
|
|
56
|
+
videoSize: {width: 0, height: 0},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
private _floatingConfig: any;
|
|
61
|
+
|
|
62
|
+
constructor(private _options: FloatingManagerOptions) {
|
|
63
|
+
this._floatingConfig = getContribConfig(
|
|
64
|
+
this._options.kalturaPlayer,
|
|
65
|
+
'ui.floating',
|
|
66
|
+
defaultFloatingConfig,
|
|
67
|
+
{
|
|
68
|
+
explicitMerge: ['presetAreasMapping'],
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const groupedPresets = PresetsUtils.groupPresetAreasByType({
|
|
73
|
+
presetAreasMapping: this._floatingConfig.presetAreasMapping,
|
|
74
|
+
acceptableTypes,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
Object.keys(groupedPresets).forEach(presetType => {
|
|
78
|
+
this._options.presetManager.add({
|
|
79
|
+
label: 'floating-manager',
|
|
80
|
+
presetAreas: groupedPresets[presetType],
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
renderChild: () => this._renderChild(FloatingPositions[presetType]),
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
this._addPlayerBindings();
|
|
86
|
+
this._updateCachedCanvas();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* initialize new floating ui item
|
|
91
|
+
* @param item
|
|
92
|
+
*/
|
|
93
|
+
//TODO push new item to relevant position array according to its' FloatingPositions value
|
|
94
|
+
add(data: FloatingItemData): FloatingItem | null {
|
|
95
|
+
const {presetManager} = this._options;
|
|
96
|
+
|
|
97
|
+
const itemOptions = {
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
presetManager,
|
|
100
|
+
...this._options,
|
|
101
|
+
data,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const item = new FloatingItem(itemOptions);
|
|
105
|
+
this._items[data.position].push(item);
|
|
106
|
+
return item;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
remove(item: FloatingItem) {
|
|
110
|
+
const positionItems = this._items[item.data.position];
|
|
111
|
+
const itemIndex = positionItems.indexOf(item);
|
|
112
|
+
if (itemIndex > -1) {
|
|
113
|
+
positionItems[itemIndex].destroy();
|
|
114
|
+
positionItems.splice(itemIndex, 1);
|
|
115
|
+
} else {
|
|
116
|
+
console.warn(`couldn't remove ${item} since it wasn't found`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
reset(): void {
|
|
121
|
+
const allItems = [
|
|
122
|
+
...this._items.VideoArea,
|
|
123
|
+
...this._items.InteractiveArea,
|
|
124
|
+
...this._items.PresetArea,
|
|
125
|
+
];
|
|
126
|
+
allItems.forEach(item => {
|
|
127
|
+
try {
|
|
128
|
+
item.destroy();
|
|
129
|
+
} catch (e) {
|
|
130
|
+
// TODO log error
|
|
131
|
+
console.warn(e);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
this._items.VideoArea = [];
|
|
136
|
+
this._items.PresetArea = [];
|
|
137
|
+
this._items.InteractiveArea = [];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private _getRendererProps(
|
|
141
|
+
props: Partial<FloatingItemProps>
|
|
142
|
+
): FloatingItemProps {
|
|
143
|
+
const {kalturaPlayer} = this._options;
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
currentTime:
|
|
147
|
+
typeof props.currentTime !== 'undefined'
|
|
148
|
+
? props.currentTime
|
|
149
|
+
: kalturaPlayer.currentTime * 1000,
|
|
150
|
+
canvas: this._cache.canvas,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private _updateCachedCanvas() {
|
|
155
|
+
this._cache.canvas = {
|
|
156
|
+
playerSize: getPlayerSize(this._options.kalturaPlayer),
|
|
157
|
+
videoSize: getVideoSize(this._options.kalturaPlayer),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private _renderItems = (position: FloatingPositions) => {
|
|
162
|
+
const props = this._getRendererProps({});
|
|
163
|
+
return this._items[position].map(item => item.renderFloatingChild(props));
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
private _renderChild = (position: FloatingPositions): ComponentChild => {
|
|
167
|
+
return (
|
|
168
|
+
<ManagedComponent
|
|
169
|
+
label={'floating-manager'}
|
|
170
|
+
renderChildren={() => this._renderItems(position)}
|
|
171
|
+
isShown={() => true}
|
|
172
|
+
ref={(ref: any) => (this._componentRef[position] = ref)}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
private _updateComponents() {
|
|
178
|
+
if (this._componentRef.InteractiveArea) {
|
|
179
|
+
this._componentRef.InteractiveArea.update();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (this._componentRef.PresetArea) {
|
|
183
|
+
this._componentRef.PresetArea.update();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (this._componentRef.VideoArea) {
|
|
187
|
+
this._componentRef.VideoArea.update();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private _addPlayerBindings() {
|
|
192
|
+
const {kalturaPlayer} = this._options;
|
|
193
|
+
|
|
194
|
+
kalturaPlayer.addEventListener(kalturaPlayer.Event.TIME_UPDATE, () => {
|
|
195
|
+
this._updateComponents();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
kalturaPlayer.addEventListener(kalturaPlayer.Event.MEDIA_LOADED, () => {
|
|
199
|
+
this._updateCachedCanvas();
|
|
200
|
+
this._updateComponents();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
kalturaPlayer.addEventListener(kalturaPlayer.Event.LOADED_DATA, () => {
|
|
204
|
+
this._updateCachedCanvas();
|
|
205
|
+
this._updateComponents();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
this._options.presetManager.on(
|
|
209
|
+
PresetManagerEventTypes.VideoResizeEvent,
|
|
210
|
+
() => {
|
|
211
|
+
this._updateCachedCanvas();
|
|
212
|
+
this._updateComponents();
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
this._options.presetManager.on(
|
|
217
|
+
PresetManagerEventTypes.PresetResizeEvent,
|
|
218
|
+
() => {
|
|
219
|
+
this._updateCachedCanvas();
|
|
220
|
+
this._updateComponents();
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {InjectedComponent} from './injected-component';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {h, Component} from 'preact';
|
|
2
|
+
import * as styles from './injected-component.scss';
|
|
3
|
+
|
|
4
|
+
export interface InjectedComponentProps {
|
|
5
|
+
onCreate: (options: {parent: HTMLDivElement}) => void;
|
|
6
|
+
onDestroy: (options: {parent: HTMLDivElement}) => void;
|
|
7
|
+
label: string;
|
|
8
|
+
fillContainer: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class InjectedComponent extends Component<InjectedComponentProps> {
|
|
12
|
+
_root = null;
|
|
13
|
+
|
|
14
|
+
shouldComponentUpdate(): boolean {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
componentDidMount(): void {
|
|
19
|
+
const {onCreate, label} = this.props;
|
|
20
|
+
|
|
21
|
+
if (!onCreate) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const parentElement = this._root;
|
|
26
|
+
if (!parentElement) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onCreate({parent: parentElement});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
componentWillUnmount(): void {
|
|
34
|
+
const {onDestroy, label} = this.props;
|
|
35
|
+
const parentElement = this._root;
|
|
36
|
+
|
|
37
|
+
if (!parentElement || !onDestroy) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onDestroy({parent: parentElement});
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
render() {
|
|
46
|
+
const {label, fillContainer} = this.props;
|
|
47
|
+
const className = fillContainer ? styles.fillContainer : '';
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
data-contrib-injected={label}
|
|
51
|
+
className={className}
|
|
52
|
+
ref={(ref: any) => (this._root = ref)}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {InjectedComponent};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {ObjectUtils} from './object-utils';
|
|
2
|
+
|
|
3
|
+
export class KalturaPlayerUtils {
|
|
4
|
+
static getPlayerConfig<T>(
|
|
5
|
+
player: any,
|
|
6
|
+
configPath: string,
|
|
7
|
+
baseConfig: T,
|
|
8
|
+
options: {explicitMerge: string[]}
|
|
9
|
+
): T {
|
|
10
|
+
const playerContribConfig = ObjectUtils.get(player.config, configPath, {});
|
|
11
|
+
|
|
12
|
+
return ObjectUtils.mergeDefaults<T>(
|
|
13
|
+
playerContribConfig as any,
|
|
14
|
+
baseConfig,
|
|
15
|
+
options
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './managed-component';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {h, Component, ComponentChild, ComponentChildren} from 'preact';
|
|
2
|
+
import * as styles from './_managed-component.scss';
|
|
3
|
+
const {
|
|
4
|
+
redux: {connect},
|
|
5
|
+
} = KalturaPlayer.ui;
|
|
6
|
+
|
|
7
|
+
type ManagedComponentState = {
|
|
8
|
+
toggler: boolean;
|
|
9
|
+
};
|
|
10
|
+
type ManagedComponentProps = {
|
|
11
|
+
isShown: () => boolean;
|
|
12
|
+
renderChildren: (playerSize: string) => ComponentChildren;
|
|
13
|
+
label: string;
|
|
14
|
+
fillContainer: boolean;
|
|
15
|
+
playerSize?: string;
|
|
16
|
+
updateOnPlayerSizeChanged?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const mapStateToProps = (state: Record<string, any>) => ({
|
|
20
|
+
playerSize: state.shell.playerSize,
|
|
21
|
+
});
|
|
22
|
+
@connect(mapStateToProps, null, null, {forwardRef: true})
|
|
23
|
+
export class ManagedComponent extends Component<
|
|
24
|
+
ManagedComponentProps,
|
|
25
|
+
ManagedComponentState
|
|
26
|
+
> {
|
|
27
|
+
|
|
28
|
+
static defaultProps = {
|
|
29
|
+
fillContainer: false,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
update() {
|
|
33
|
+
this.setState((prev: ManagedComponentState) => {
|
|
34
|
+
return {
|
|
35
|
+
toggler: !prev.toggler,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
shouldComponentUpdate(prevProps: Readonly<ManagedComponentProps>): boolean {
|
|
41
|
+
const {updateOnPlayerSizeChanged, playerSize} = this.props;
|
|
42
|
+
return (
|
|
43
|
+
(updateOnPlayerSizeChanged && prevProps.playerSize !== playerSize) ||
|
|
44
|
+
prevProps.playerSize === playerSize
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
componentDidMount(): void {
|
|
49
|
+
this.setState({
|
|
50
|
+
toggler: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
render() {
|
|
55
|
+
const {fillContainer, isShown, playerSize} = this.props;
|
|
56
|
+
if (!isShown()) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
data-contrib-item={this.props.label}
|
|
63
|
+
className={[
|
|
64
|
+
`${fillContainer ? styles.fillContainer : ''}`,
|
|
65
|
+
styles.inlineContainer,
|
|
66
|
+
].join(' ')}>
|
|
67
|
+
{this.props.renderChildren(playerSize!)}
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export class ObjectUtils {
|
|
2
|
+
/**
|
|
3
|
+
* @param {T} data - The data to copy.
|
|
4
|
+
* @returns {T} - The copied data.
|
|
5
|
+
*/
|
|
6
|
+
public static copyDeep<T extends Record<string, any>>(data: T): T {
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
let node;
|
|
9
|
+
if (Array.isArray(data)) {
|
|
10
|
+
node = data.length > 0 ? data.slice(0) : [];
|
|
11
|
+
node.forEach((e, i) => {
|
|
12
|
+
if (
|
|
13
|
+
(typeof e === 'object' && e !== {}) ||
|
|
14
|
+
(Array.isArray(e) && e.length > 0)
|
|
15
|
+
) {
|
|
16
|
+
node[i] = ObjectUtils.copyDeep(e);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
} else if (typeof data === 'object') {
|
|
20
|
+
node = Object.assign({}, data);
|
|
21
|
+
Object.keys(node).forEach(key => {
|
|
22
|
+
if (
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
(typeof node[key] === 'object' && node[key] !== {}) ||
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
(Array.isArray(node[key]) && node[key].length > 0)
|
|
27
|
+
) {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
node[key] = ObjectUtils.copyDeep(node[key]);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
node = data;
|
|
34
|
+
}
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
return node;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {T} item - The item to check.
|
|
41
|
+
* @returns {T} - Whether the item is an object.
|
|
42
|
+
*/
|
|
43
|
+
public static isObject(item: any) {
|
|
44
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {T} target - The target object.
|
|
49
|
+
* @param {T} sources - The objects to merge.
|
|
50
|
+
* @returns {T} - The merged object.
|
|
51
|
+
*/
|
|
52
|
+
public static mergeDeep<T extends Record<string, any>>(
|
|
53
|
+
target: Partial<T>,
|
|
54
|
+
sources: Partial<T>[],
|
|
55
|
+
extra?: {explicitMerge?: string[]}
|
|
56
|
+
): Partial<T> {
|
|
57
|
+
if (!sources.length) {
|
|
58
|
+
return target;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const explicitMerge: string[] = (extra ? extra.explicitMerge : null) || [];
|
|
62
|
+
const source = sources.shift();
|
|
63
|
+
if (ObjectUtils.isObject(target) && ObjectUtils.isObject(source)) {
|
|
64
|
+
for (const key in source) {
|
|
65
|
+
if (ObjectUtils.isObject(source[key])) {
|
|
66
|
+
if (!target[key]) Object.assign(target, {[key]: {}});
|
|
67
|
+
|
|
68
|
+
if (explicitMerge.indexOf(key) !== -1) {
|
|
69
|
+
target[key] = ObjectUtils.explicitFlatMerge<any>(
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
target[key],
|
|
72
|
+
source[key]
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
ObjectUtils.mergeDeep(target[key], [source[key]], extra);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
Object.assign(target, {[key]: source[key]});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return ObjectUtils.mergeDeep(target, sources, extra);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public static mergeDefaults<T extends Record<string, any>>(
|
|
87
|
+
source: Partial<T>,
|
|
88
|
+
defaults: T,
|
|
89
|
+
extra?: {explicitMerge?: string[]}
|
|
90
|
+
): T {
|
|
91
|
+
return ObjectUtils.mergeDeep({}, [defaults, source], extra) as T;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* source properties will override all equivalent properties in target. null or empty objects properties in source
|
|
96
|
+
* will cause the removal of these properties in target.
|
|
97
|
+
* all other data will be merged
|
|
98
|
+
* @param initialObject
|
|
99
|
+
* @param source
|
|
100
|
+
*/
|
|
101
|
+
public static explicitFlatMerge<T extends Record<string, any>>(
|
|
102
|
+
initialObject: Partial<T>,
|
|
103
|
+
source: Partial<T>
|
|
104
|
+
): any {
|
|
105
|
+
const result = {...initialObject};
|
|
106
|
+
Object.keys(source).forEach(key => {
|
|
107
|
+
// @ts-ignore
|
|
108
|
+
if (source[key] === null || Object.keys(source[key]).length === 0) {
|
|
109
|
+
delete result[key];
|
|
110
|
+
} else {
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
// https://github.com/microsoft/TypeScript/issues/31661
|
|
113
|
+
result[key] = source[key];
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public static get(
|
|
120
|
+
obj: Record<string, any>,
|
|
121
|
+
path: string,
|
|
122
|
+
defaultValue: any
|
|
123
|
+
): any {
|
|
124
|
+
function stringToPath(path: string) {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
const output = [];
|
|
127
|
+
// Split to an array with dot notation
|
|
128
|
+
path.split('.').forEach(item => {
|
|
129
|
+
// Split to an array with bracket notation
|
|
130
|
+
item.split(/\[([^}]+)\]/g).forEach(key => {
|
|
131
|
+
// Push to the new array
|
|
132
|
+
if (key.length > 0) {
|
|
133
|
+
output.push(key);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
// @ts-ignore
|
|
138
|
+
return output;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Get the path as an array
|
|
142
|
+
const pathArray = stringToPath(path);
|
|
143
|
+
|
|
144
|
+
let current = obj;
|
|
145
|
+
|
|
146
|
+
// For each item in the path, dig into the object
|
|
147
|
+
for (let i = 0; i < pathArray.length; i++) {
|
|
148
|
+
// If the item isn't found, return the default (or null)
|
|
149
|
+
if (!current[pathArray[i]]) return defaultValue;
|
|
150
|
+
|
|
151
|
+
// Otherwise, update the current value
|
|
152
|
+
current = current[pathArray[i]];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return current;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class PlayerContribRegistry {
|
|
2
|
+
private _cache: Record<string, {instance: any}> = {};
|
|
3
|
+
|
|
4
|
+
static get(player: any): PlayerContribRegistry {
|
|
5
|
+
player.__contrib__ = player.__contrib__ || {};
|
|
6
|
+
player.__contrib__.services =
|
|
7
|
+
player.__contrib__.services || new PlayerContribRegistry();
|
|
8
|
+
return player.__contrib__.services;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
private constructor() {}
|
|
12
|
+
|
|
13
|
+
public get(token: string): any {
|
|
14
|
+
const result = this._cache[token];
|
|
15
|
+
|
|
16
|
+
if (!result) {
|
|
17
|
+
throw new Error(`cannot find resource with token ${token}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public register<T>(token: string, creator: () => T): T {
|
|
24
|
+
let requestedResource = this._cache[token];
|
|
25
|
+
|
|
26
|
+
if (!requestedResource) {
|
|
27
|
+
requestedResource = this._cache[token] = {
|
|
28
|
+
instance: creator(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return requestedResource.instance;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {PlayerSize, VideoSize} from './common-types';
|
|
2
|
+
|
|
3
|
+
export function getPlayerSize(
|
|
4
|
+
kalturaPlayer: any
|
|
5
|
+
): PlayerSize {
|
|
6
|
+
return kalturaPlayer ? kalturaPlayer.dimensions : {width: 0, height: 0};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getVideoSize(
|
|
10
|
+
kalturaPlayer: any
|
|
11
|
+
): VideoSize {
|
|
12
|
+
if (!kalturaPlayer) {
|
|
13
|
+
return {width: 0, height: 0};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const videoTrack = kalturaPlayer.getActiveTracks().video;
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
!videoTrack ||
|
|
20
|
+
videoTrack.width === undefined ||
|
|
21
|
+
videoTrack.height === undefined
|
|
22
|
+
) {
|
|
23
|
+
// fallback - mainly for Safari
|
|
24
|
+
if (kalturaPlayer.getVideoElement()) {
|
|
25
|
+
return {
|
|
26
|
+
width: kalturaPlayer.getVideoElement().videoWidth,
|
|
27
|
+
height: kalturaPlayer.getVideoElement().videoHeight,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {width: 0, height: 0};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
width: videoTrack.width,
|
|
35
|
+
height: videoTrack.height,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {ComponentChild} from 'preact';
|
|
2
|
+
|
|
3
|
+
export enum ReservedPresetNames {
|
|
4
|
+
Playback = 'Playback',
|
|
5
|
+
Live = 'Live',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export enum ReservedPresetAreas {
|
|
9
|
+
'PresetFloating' = 'PresetFloating',
|
|
10
|
+
'BottomBarLeftControls' = 'BottomBarLeftControls',
|
|
11
|
+
'BottomBarRightControls' = 'BottomBarRightControls',
|
|
12
|
+
'TopBarLeftControls' = 'TopBarLeftControls',
|
|
13
|
+
'TopBarRightControls' = 'TopBarRightControls',
|
|
14
|
+
'SidePanelTop' = 'SidePanelTop',
|
|
15
|
+
'SidePanelLeft' = 'SidePanelLeft',
|
|
16
|
+
'SidePanelRight' = 'SidePanelRight',
|
|
17
|
+
'SidePanelBottom' = 'SidePanelBottom',
|
|
18
|
+
'PresetArea' = 'PresetArea',
|
|
19
|
+
'InteractiveArea' = 'InteractiveArea',
|
|
20
|
+
'PlayerArea' = 'PlayerArea',
|
|
21
|
+
'VideoArea' = 'VideoArea',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export enum RelativeToTypes {
|
|
25
|
+
Before = 'Before',
|
|
26
|
+
After = 'After',
|
|
27
|
+
Replace = 'Replace',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PresetItemData {
|
|
31
|
+
label: string;
|
|
32
|
+
fillContainer?: boolean;
|
|
33
|
+
isolateComponent?: boolean;
|
|
34
|
+
presetAreas: Record<
|
|
35
|
+
ReservedPresetNames | string,
|
|
36
|
+
ReservedPresetAreas | string
|
|
37
|
+
>;
|
|
38
|
+
renderChild: () => ComponentChild;
|
|
39
|
+
relativeTo?: {
|
|
40
|
+
type: RelativeToTypes;
|
|
41
|
+
name: string;
|
|
42
|
+
};
|
|
43
|
+
}
|