@24i/bigscreen-sdk 1.0.2-alpha.2074 → 1.0.2-alpha.2089
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/package.json +2 -2
- package/packages/developer-tools/src/TechnicalInfo/styles/TechnicalInfo.scss +1 -0
- package/packages/developer-tools/src/TechnicalInfo/utils/emeSupport.ts +6 -2
- package/packages/driver-tizen/src/DeviceTizen.ts +3 -1
- package/packages/driver-vidaa/src/DeviceVidaa.ts +7 -1
- package/packages/driver-vidaa/src/__mocks__/vidaa.ts +1 -0
- package/packages/driver-vidaa/src/constants.ts +8 -0
- package/packages/driver-vidaa/src/types.ts +8 -0
- package/packages/focus/src/Layout/Matrix.tsx +1 -2
- package/packages/grid/src/Base/Base.tsx +25 -6
- package/packages/grid/src/Base/MouseNavigation/MouseNavigation.tsx +82 -0
- package/packages/grid/src/Base/MouseNavigation/MouseNavigationFallback.ts +4 -0
- package/packages/grid/src/Base/MouseNavigation/index.tizen.tv.ts +1 -0
- package/packages/grid/src/Base/MouseNavigation/index.ts +1 -0
- package/packages/grid/src/Base/MouseNavigation/index.webos.tv.ts +1 -0
- package/packages/grid/src/Base/MouseNavigation/index.webtv.ts +1 -0
- package/packages/grid/src/Base/interface.ts +47 -0
- package/packages/grid/src/UnifiedGridController/UnifiedGridController.ts +6 -1
- package/packages/i18n/src/middlewares/i18next/Plurals/Plurals.ts +2 -2
- package/packages/keyboard/src/WhitelabelKeyboard/Keyboard.tsx +6 -2
- package/packages/list/src/Base/Base.tsx +4 -2
- package/packages/list/src/Base/MouseNavigation/MouseNavigation.tsx +33 -9
- package/packages/list/src/EdgeOffsetList/EdgeOffsetList.tsx +3 -1
- package/packages/list/src/types.ts +6 -0
- package/packages/menu/src/MenuAndContentContainer/MenuAndContentContainer.tsx +31 -16
- package/packages/menu/src/MenuAndContentContainer/interface.ts +0 -8
- package/packages/menu/src/WhitelabelMenu/SideMenu.scss +1 -1
- package/packages/menu/src/WhitelabelMenu/SideMenu.tsx +1 -1
- package/packages/menu/src/WhitelabelMenu/_animated.scss +1 -1
- package/packages/menu/src/WhitelabelMenu/rtl.scss +1 -1
- package/packages/modal-service/src/ModalService.tsx +3 -1
- package/packages/mouse-navigation/src/MouseNavigation.tsx +18 -0
- package/packages/player-ui/src/PlayerUI.tsx +1 -5
- package/packages/types-bigscreen-jsx/index.d.ts +1 -1
- package/packages/utils/src/counter.ts +3 -1
- package/packages/utils/src/xhr/xhrSendRetry.ts +2 -2
- package/packages/volume-control/src/__mocks__/VolumeControlUIMock.tsx +6 -2
- package/packages/grid/src/Base/Base.mouse.tsx +0 -24
- package/packages/grid/src/Base/index.tizen.tv.ts +0 -1
- package/packages/grid/src/Base/index.webos.tv.ts +0 -1
- package/packages/grid/src/Base/index.webtv.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24i/bigscreen-sdk",
|
|
3
|
-
"version": "1.0.2-alpha.
|
|
3
|
+
"version": "1.0.2-alpha.2089",
|
|
4
4
|
"description": "SmartApps BIGscreen SDK monorepo",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"homepage": "https://github.com/24i/smartapps-bigscreen-sdk#readme",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@24i/player-base": "6.10.0",
|
|
41
|
-
"@24i/smartapps-datalayer": "2.3.
|
|
41
|
+
"@24i/smartapps-datalayer": "2.3.3",
|
|
42
42
|
"@sentry/browser": "^7.8.0",
|
|
43
43
|
"@types/prop-types": "^15.7.5",
|
|
44
44
|
"@types/scheduler": "^0.16.1",
|
|
@@ -30,8 +30,12 @@ function isKeySystemSupported(keySystem: string, config: MediaKeySystemConfigura
|
|
|
30
30
|
return new Promise((resolve) => {
|
|
31
31
|
try {
|
|
32
32
|
window.navigator.requestMediaKeySystemAccess(keySystem, config)
|
|
33
|
-
.then(() => {
|
|
34
|
-
|
|
33
|
+
.then(() => {
|
|
34
|
+
resolve(true);
|
|
35
|
+
})
|
|
36
|
+
.catch(() => {
|
|
37
|
+
resolve(false);
|
|
38
|
+
});
|
|
35
39
|
} catch (e) {
|
|
36
40
|
resolve(false);
|
|
37
41
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ScreenSaverStatus,
|
|
5
5
|
VolumeRange,
|
|
6
6
|
} from '@24i/bigscreen-sdk/driver-base';
|
|
7
|
+
import { NetworkConnectionTypeMap } from './constants';
|
|
7
8
|
import { getPlatformInfo } from './formatUserAgent';
|
|
8
9
|
import { HisenseVidaaApi } from './types';
|
|
9
10
|
import { getKeyMap } from './keymap';
|
|
@@ -118,7 +119,12 @@ export class DeviceVidaa extends DeviceBase {
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
async getConnectionType(): Promise<ConnectionType> {
|
|
121
|
-
|
|
122
|
+
try {
|
|
123
|
+
const netType = window.Hisense_GetNetType();
|
|
124
|
+
return NetworkConnectionTypeMap[netType] || 'unknown';
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error('[DeviceVidaa] Failed getConnectionType', e);
|
|
127
|
+
}
|
|
122
128
|
return 'unknown';
|
|
123
129
|
}
|
|
124
130
|
|
|
@@ -6,6 +6,7 @@ export const mockHisenseVidaaApi: HisenseVidaaApi = {
|
|
|
6
6
|
Hisense_GetFirmWareVersion: () => 'V0000.01.00Q.L0301',
|
|
7
7
|
Hisense_Get4KSupportState: () => true,
|
|
8
8
|
Hisense_GetDeviceID: () => '861003009000001000000641123456789012',
|
|
9
|
+
Hisense_GetNetType: () => 'wireless',
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
// Key constants are set to random number values
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type HisenseNetType = 'OFF' | 'wired' | 'wireless';
|
|
2
|
+
|
|
1
3
|
export interface HisenseVidaaApi {
|
|
2
4
|
/**
|
|
3
5
|
* This interface will retrieve Hisense Unique ID for the device.
|
|
@@ -27,6 +29,12 @@ export interface HisenseVidaaApi {
|
|
|
27
29
|
* @return a string that represents the TV model name.
|
|
28
30
|
*/
|
|
29
31
|
Hisense_GetModelName: () => string,
|
|
32
|
+
/**
|
|
33
|
+
* This interface retrieves the network type of the device.
|
|
34
|
+
* @return a string that represents the network type for the device.
|
|
35
|
+
* The one from "OFF", "wired", "wireless".
|
|
36
|
+
*/
|
|
37
|
+
Hisense_GetNetType: () => HisenseNetType,
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
export type HisenseVidaaKeys = {
|
|
@@ -154,8 +154,7 @@ export class Matrix extends Component<Props> implements IFocusable {
|
|
|
154
154
|
isDifferentReferenceFromCurrent(index: Index2D): boolean {
|
|
155
155
|
const { current } = this.getRefAt(this.index);
|
|
156
156
|
const { current: searched } = this.getRefAt(index);
|
|
157
|
-
|
|
158
|
-
return false;
|
|
157
|
+
return current !== searched && searched !== null;
|
|
159
158
|
}
|
|
160
159
|
|
|
161
160
|
isSameReferenceAsCurrent(index: Index2D): boolean {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { createRef, Component, Reference, DeclareProps } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { device } from '@24i/bigscreen-sdk/device';
|
|
3
|
-
import { MouseNavigation } from '@24i/bigscreen-sdk/mouse-navigation';
|
|
4
3
|
import { Scroller } from '@24i/bigscreen-sdk/scroller';
|
|
5
4
|
import { stopEvent } from '@24i/bigscreen-sdk/utils/stopEvent';
|
|
6
5
|
import { noop } from '@24i/bigscreen-sdk/utils/noop';
|
|
7
6
|
import { forEach } from '@24i/bigscreen-sdk/perf-utils/array';
|
|
8
7
|
import { createTimeout, createCounter, ICounter } from '@24i/bigscreen-sdk/utils';
|
|
8
|
+
import { MouseNavigation } from './MouseNavigation';
|
|
9
9
|
import { FastFocusingOptimizer } from '../FastFocusingOptimizer/FastFocusingOptimizer';
|
|
10
10
|
import { SharedProps, Item } from '../types';
|
|
11
|
+
import { MouseNavigation as IMouseNavigation } from './interface';
|
|
11
12
|
|
|
12
13
|
export type Props<T extends Item<U>, U> = Omit<SharedProps<T, U>, 'scrollStep'> & {
|
|
13
14
|
forward: () => boolean,
|
|
@@ -21,7 +22,6 @@ export type Props<T extends Item<U>, U> = Omit<SharedProps<T, U>, 'scrollStep'>
|
|
|
21
22
|
adjustFocusFromTarget?: (itemRefIndex: number, groupRefIndex: number) => void,
|
|
22
23
|
horizontal?: boolean,
|
|
23
24
|
limit?: number,
|
|
24
|
-
mrcuRef?: Reference<MouseNavigation>;
|
|
25
25
|
shouldApplySlowdown?: () => boolean,
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -55,6 +55,8 @@ export class GridBase<T extends Item<U>, U>
|
|
|
55
55
|
|
|
56
56
|
scrollerDom = createRef<HTMLDivElement>();
|
|
57
57
|
|
|
58
|
+
mrcuRef = createRef<IMouseNavigation>();
|
|
59
|
+
|
|
58
60
|
itemRefs: Reference<T>[] = [];
|
|
59
61
|
|
|
60
62
|
groupRefs: Reference<HTMLDivElement>[] = [];
|
|
@@ -151,14 +153,13 @@ export class GridBase<T extends Item<U>, U>
|
|
|
151
153
|
onWheel = (event: WheelEvent) => {
|
|
152
154
|
const {
|
|
153
155
|
forwardGroup, backwardGroup, shouldApplySlowdown,
|
|
154
|
-
mrcuRef,
|
|
155
156
|
} = this.props;
|
|
156
157
|
let processed;
|
|
157
158
|
if (event.deltaY > 0) processed = shouldApplySlowdown() || forwardGroup();
|
|
158
159
|
else if (event.deltaY < 0) processed = shouldApplySlowdown() || backwardGroup();
|
|
159
160
|
if (processed) {
|
|
160
161
|
stopEvent(event);
|
|
161
|
-
mrcuRef
|
|
162
|
+
this.mrcuRef.current?.handleArrowState();
|
|
162
163
|
if (this.fastScrollingCounter) {
|
|
163
164
|
this.fastScrollingCounter.add();
|
|
164
165
|
this.fakeWheelStop();
|
|
@@ -434,7 +435,15 @@ export class GridBase<T extends Item<U>, U>
|
|
|
434
435
|
}
|
|
435
436
|
|
|
436
437
|
render() {
|
|
437
|
-
const {
|
|
438
|
+
const {
|
|
439
|
+
horizontal,
|
|
440
|
+
className,
|
|
441
|
+
forwardGroup,
|
|
442
|
+
backwardGroup,
|
|
443
|
+
shouldShowMrcuForward,
|
|
444
|
+
shouldShowMrcuBackward,
|
|
445
|
+
} = this.props;
|
|
446
|
+
|
|
438
447
|
return (
|
|
439
448
|
<Scroller
|
|
440
449
|
className={className}
|
|
@@ -443,7 +452,17 @@ export class GridBase<T extends Item<U>, U>
|
|
|
443
452
|
onKeyDown={this.onKeyDown}
|
|
444
453
|
horizontal={horizontal}
|
|
445
454
|
>
|
|
446
|
-
{this.renderData()}
|
|
455
|
+
<>{this.renderData()}</>
|
|
456
|
+
<MouseNavigation
|
|
457
|
+
// @ts-ignore - needed to convert fallback (false) to interface
|
|
458
|
+
ref={this.mrcuRef}
|
|
459
|
+
getMountingPoint={() => this.scroller.current!.wrapRef}
|
|
460
|
+
horizontal={horizontal}
|
|
461
|
+
forward={forwardGroup}
|
|
462
|
+
backward={backwardGroup}
|
|
463
|
+
shouldShowMrcuForward={shouldShowMrcuForward}
|
|
464
|
+
shouldShowMrcuBackward={shouldShowMrcuBackward}
|
|
465
|
+
/>
|
|
447
466
|
</Scroller>
|
|
448
467
|
);
|
|
449
468
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Component, createRef, removeNode } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
+
import { MouseNavigation as MouseNavigationBase } from '@24i/bigscreen-sdk/mouse-navigation';
|
|
3
|
+
import { device, DeviceEventMap } from '@24i/bigscreen-sdk/device';
|
|
4
|
+
import {
|
|
5
|
+
MouseNavigationProps as Props,
|
|
6
|
+
MouseNavigation as IMouseNavigation,
|
|
7
|
+
} from '../interface';
|
|
8
|
+
|
|
9
|
+
export class MouseNavigation extends Component<Props> implements IMouseNavigation {
|
|
10
|
+
private readonly wrapper = createRef<HTMLDivElement>();
|
|
11
|
+
|
|
12
|
+
private readonly mouseNavigationBase = createRef<MouseNavigationBase>();
|
|
13
|
+
|
|
14
|
+
private isMouseEnabled = true;
|
|
15
|
+
|
|
16
|
+
componentDidMount() {
|
|
17
|
+
this.handleWheelListener();
|
|
18
|
+
device.addEventListener('mouseactive', this.mouseListener);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
componentWillUnmount() {
|
|
22
|
+
this.handleWheelListener();
|
|
23
|
+
device.removeEventListener('mouseactive', this.mouseListener);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
handleWheelListener() {
|
|
27
|
+
if (this.isMouseEnabled && device.isMouseUsed()) {
|
|
28
|
+
this.renderArrows();
|
|
29
|
+
} else {
|
|
30
|
+
this.destroyArrows();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
handleArrowState() {
|
|
35
|
+
this.mouseNavigationBase?.current?.handleArrowState();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
mouseListener: DeviceEventMap['mouseactive'] = ({ isMouseActive }) => {
|
|
39
|
+
this.isMouseEnabled = isMouseActive;
|
|
40
|
+
this.handleWheelListener();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
destroyArrows() {
|
|
44
|
+
if (!this.wrapper.current) return;
|
|
45
|
+
removeNode(this.wrapper);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
renderArrows() {
|
|
49
|
+
const {
|
|
50
|
+
horizontal,
|
|
51
|
+
forward,
|
|
52
|
+
backward,
|
|
53
|
+
shouldShowMrcuForward,
|
|
54
|
+
shouldShowMrcuBackward,
|
|
55
|
+
getMountingPoint,
|
|
56
|
+
} = this.props;
|
|
57
|
+
|
|
58
|
+
const direction = horizontal ? 'horizontal' : 'vertical';
|
|
59
|
+
|
|
60
|
+
this.appendMount(
|
|
61
|
+
<div ref={this.wrapper} className="mouse-navigation">
|
|
62
|
+
<MouseNavigationBase
|
|
63
|
+
// @ts-ignore - needed to convert fallback (false) to interface
|
|
64
|
+
ref={this.mouseNavigationBase}
|
|
65
|
+
getMountingPoint={() => this.wrapper}
|
|
66
|
+
direction={direction}
|
|
67
|
+
forward={forward}
|
|
68
|
+
backward={backward}
|
|
69
|
+
shouldShowMrcuForward={shouldShowMrcuForward}
|
|
70
|
+
shouldShowMrcuBackward={shouldShowMrcuBackward}
|
|
71
|
+
>
|
|
72
|
+
{null as unknown as JSX.Element}
|
|
73
|
+
</MouseNavigationBase>
|
|
74
|
+
</div>,
|
|
75
|
+
getMountingPoint(),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
render() {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MouseNavigation } from './MouseNavigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MouseNavigation } from './MouseNavigationFallback';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MouseNavigation } from './MouseNavigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MouseNavigation } from './MouseNavigation';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Reference, Component } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
+
|
|
3
|
+
export type MouseNavigationProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Function to call on the press of the right arrow.
|
|
6
|
+
*/
|
|
7
|
+
forward(): boolean,
|
|
8
|
+
/**
|
|
9
|
+
* Function to call on the press of the left arrow.
|
|
10
|
+
*/
|
|
11
|
+
backward(): boolean,
|
|
12
|
+
/**
|
|
13
|
+
* Function to call on the press of the down arrow.
|
|
14
|
+
*/
|
|
15
|
+
forwardGroup?(): boolean,
|
|
16
|
+
/**
|
|
17
|
+
* Function to call on the press of the up arrow.
|
|
18
|
+
*/
|
|
19
|
+
backwardGroup?(): boolean,
|
|
20
|
+
/**
|
|
21
|
+
* Function which determines whether to show the forward arrow.
|
|
22
|
+
*/
|
|
23
|
+
shouldShowMrcuForward?(): boolean,
|
|
24
|
+
/**
|
|
25
|
+
* Function which determines whether to show the backward arrow.
|
|
26
|
+
*/
|
|
27
|
+
shouldShowMrcuBackward?(): boolean,
|
|
28
|
+
/**
|
|
29
|
+
* Returns a reference to the element where your `children` should be rendered.
|
|
30
|
+
*/
|
|
31
|
+
getMountingPoint(): Reference<HTMLElement>;
|
|
32
|
+
/**
|
|
33
|
+
* Property determines whether navigation is horizontal.
|
|
34
|
+
*/
|
|
35
|
+
horizontal?: boolean,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export interface MouseNavigation extends Component<MouseNavigationProps> {
|
|
39
|
+
/**
|
|
40
|
+
* Function to disable showing an arrow in the given direction.
|
|
41
|
+
*/
|
|
42
|
+
handleArrowState(): void,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface MouseNavigationComponent {
|
|
46
|
+
new (props: MouseNavigationProps): MouseNavigation,
|
|
47
|
+
}
|
|
@@ -295,6 +295,8 @@ export class UnifiedGridController<T> implements IUnifiedGridController<T> {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
focusToIndex(dataIndex: number, animate = false) {
|
|
298
|
+
const { grid } = this;
|
|
299
|
+
const base = grid.base.current!;
|
|
298
300
|
const targetScrollIndex = this.itemIndexToScrollIndex(dataIndex);
|
|
299
301
|
if (targetScrollIndex > this.scrollIndex) {
|
|
300
302
|
this.adjustGroupsOffsetsForward(targetScrollIndex);
|
|
@@ -304,8 +306,9 @@ export class UnifiedGridController<T> implements IUnifiedGridController<T> {
|
|
|
304
306
|
if (targetScrollIndex !== this.scrollIndex) {
|
|
305
307
|
this.scroll(targetScrollIndex, animate);
|
|
306
308
|
}
|
|
307
|
-
|
|
309
|
+
base.index = dataIndex;
|
|
308
310
|
this.focusCurrentItem();
|
|
311
|
+
base.mrcuRef.current?.handleArrowState();
|
|
309
312
|
}
|
|
310
313
|
|
|
311
314
|
protected focusScrollWrap() {
|
|
@@ -521,6 +524,7 @@ export class UnifiedGridController<T> implements IUnifiedGridController<T> {
|
|
|
521
524
|
forEach(this.groups, (group, index) => {
|
|
522
525
|
this.updateItemsInGroup(group, index * itemsInGroup);
|
|
523
526
|
});
|
|
527
|
+
base.mrcuRef.current?.handleArrowState();
|
|
524
528
|
}
|
|
525
529
|
|
|
526
530
|
prependData(data: T[]) {
|
|
@@ -546,5 +550,6 @@ export class UnifiedGridController<T> implements IUnifiedGridController<T> {
|
|
|
546
550
|
this.scrollIndexToPixels(this.scrollIndex),
|
|
547
551
|
);
|
|
548
552
|
this.focusCurrentItem();
|
|
553
|
+
base.mrcuRef.current?.handleArrowState();
|
|
549
554
|
}
|
|
550
555
|
}
|
|
@@ -45,8 +45,8 @@ const isCountInInterval = (count: number, interval: string) => {
|
|
|
45
45
|
if (numbers.length === 1 && parseInt(numbers[0], 10) === count) return true;
|
|
46
46
|
const from = parseInt(numbers[0], 10);
|
|
47
47
|
const to = numbers[1] === 'inf' ? Infinity : parseInt(numbers[1], 10);
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
return count >= from && count <= to;
|
|
49
|
+
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
const shouldUseInterval = (
|
|
@@ -145,7 +145,9 @@ export class Keyboard extends KeyboardBase<Layouts, Props> {
|
|
|
145
145
|
<Interactable
|
|
146
146
|
ref={this.keyRefs.space}
|
|
147
147
|
className="key key-wide key-space"
|
|
148
|
-
onPress={() => {
|
|
148
|
+
onPress={() => {
|
|
149
|
+
this.onKey(' ');
|
|
150
|
+
}}
|
|
149
151
|
>
|
|
150
152
|
<div className="key-background">
|
|
151
153
|
{texts.space}
|
|
@@ -208,7 +210,9 @@ export class Keyboard extends KeyboardBase<Layouts, Props> {
|
|
|
208
210
|
<Interactable
|
|
209
211
|
ref={this.keyRefs.space}
|
|
210
212
|
className="key key-wide key-space"
|
|
211
|
-
onPress={() => {
|
|
213
|
+
onPress={() => {
|
|
214
|
+
this.onKey(' ');
|
|
215
|
+
}}
|
|
212
216
|
>
|
|
213
217
|
<div className="key-background">
|
|
214
218
|
{texts.space}
|
|
@@ -49,6 +49,8 @@ export class ListBase<T extends Item<U>, U>
|
|
|
49
49
|
|
|
50
50
|
mrcuRef = createRef<IMouseNavigation>();
|
|
51
51
|
|
|
52
|
+
// mrcuRef2: Reference<HTMLDivElement>;
|
|
53
|
+
|
|
52
54
|
itemRefs: Reference<T>[] = [];
|
|
53
55
|
|
|
54
56
|
index = 0;
|
|
@@ -344,7 +346,7 @@ export class ListBase<T extends Item<U>, U>
|
|
|
344
346
|
}
|
|
345
347
|
|
|
346
348
|
render() {
|
|
347
|
-
const { horizontal, className } = this.props;
|
|
349
|
+
const { horizontal, className, mrcuMountingPoint } = this.props;
|
|
348
350
|
return (
|
|
349
351
|
<Scroller
|
|
350
352
|
className={className}
|
|
@@ -357,7 +359,7 @@ export class ListBase<T extends Item<U>, U>
|
|
|
357
359
|
<MouseNavigation
|
|
358
360
|
// @ts-ignore - needed to convert fallback (false) to interface
|
|
359
361
|
ref={this.mrcuRef}
|
|
360
|
-
getMountingPoint={() => this.scroller.current!.wrapRef}
|
|
362
|
+
getMountingPoint={() => mrcuMountingPoint || this.scroller.current!.wrapRef}
|
|
361
363
|
{...this.props}
|
|
362
364
|
/>
|
|
363
365
|
</Scroller>
|
|
@@ -1,24 +1,48 @@
|
|
|
1
|
-
import { Component, createRef } from '@24i/bigscreen-sdk/jsx';
|
|
1
|
+
import { Component, createRef, removeNode } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { MouseNavigation as MouseNavigationBase } from '@24i/bigscreen-sdk/mouse-navigation';
|
|
3
|
-
import { device } from '@24i/bigscreen-sdk/device';
|
|
3
|
+
import { device, DeviceEventMap } from '@24i/bigscreen-sdk/device';
|
|
4
4
|
import {
|
|
5
5
|
MouseNavigationProps as Props,
|
|
6
6
|
MouseNavigation as IMouseNavigation,
|
|
7
7
|
} from '../interface';
|
|
8
8
|
|
|
9
9
|
export class MouseNavigation extends Component<Props> implements IMouseNavigation {
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly wrapper = createRef<HTMLDivElement>();
|
|
11
11
|
|
|
12
|
-
private readonly
|
|
12
|
+
private readonly mouseNavigationBase = createRef<MouseNavigationBase>();
|
|
13
|
+
|
|
14
|
+
private isMouseEnabled = true;
|
|
13
15
|
|
|
14
16
|
componentDidMount() {
|
|
15
|
-
|
|
17
|
+
this.handleWheelListener();
|
|
18
|
+
device.addEventListener('mouseactive', this.mouseListener);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
componentWillUnmount() {
|
|
22
|
+
this.handleWheelListener();
|
|
23
|
+
device.removeEventListener('mouseactive', this.mouseListener);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
handleWheelListener() {
|
|
27
|
+
if (this.isMouseEnabled && device.isMouseUsed()) {
|
|
16
28
|
this.renderArrows();
|
|
29
|
+
} else {
|
|
30
|
+
this.destroyArrows();
|
|
17
31
|
}
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
handleArrowState() {
|
|
21
|
-
this.
|
|
35
|
+
this.mouseNavigationBase?.current?.handleArrowState();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
mouseListener: DeviceEventMap['mouseactive'] = ({ isMouseActive }) => {
|
|
39
|
+
this.isMouseEnabled = isMouseActive;
|
|
40
|
+
this.handleWheelListener();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
destroyArrows() {
|
|
44
|
+
if (!this.wrapper.current) return;
|
|
45
|
+
removeNode(this.wrapper);
|
|
22
46
|
}
|
|
23
47
|
|
|
24
48
|
renderArrows() {
|
|
@@ -34,11 +58,11 @@ export class MouseNavigation extends Component<Props> implements IMouseNavigatio
|
|
|
34
58
|
const direction = horizontal ? 'horizontal' : 'vertical';
|
|
35
59
|
|
|
36
60
|
this.appendMount(
|
|
37
|
-
<div ref={this.
|
|
61
|
+
<div ref={this.wrapper} className="mouse-navigation">
|
|
38
62
|
<MouseNavigationBase
|
|
39
63
|
// @ts-ignore - needed to convert fallback (false) to interface
|
|
40
|
-
ref={this.
|
|
41
|
-
getMountingPoint={() => this.
|
|
64
|
+
ref={this.mouseNavigationBase}
|
|
65
|
+
getMountingPoint={() => this.wrapper}
|
|
42
66
|
direction={direction}
|
|
43
67
|
forward={forward}
|
|
44
68
|
backward={backward}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createRef, DeclareProps } from '@24i/bigscreen-sdk/jsx';
|
|
1
|
+
import { Component, createRef, DeclareProps, Reference } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { IFocusable } from '@24i/bigscreen-sdk/focus';
|
|
3
3
|
import { noop } from '@24i/bigscreen-sdk/utils/noop';
|
|
4
4
|
import { ListBase } from '../Base';
|
|
@@ -29,6 +29,8 @@ export class EdgeOffsetList<T extends Item<U>, U>
|
|
|
29
29
|
*/
|
|
30
30
|
base = createRef<ListBase<T, U>>();
|
|
31
31
|
|
|
32
|
+
//mrcuRef = createRef<HTMLDivElement>();
|
|
33
|
+
|
|
32
34
|
/**
|
|
33
35
|
* Unified controller for leveraging common behaviour
|
|
34
36
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Reference, Component } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { EasingType } from '@24i/bigscreen-sdk/animations';
|
|
3
|
+
import { HtmlAttributes } from 'csstype';
|
|
3
4
|
|
|
4
5
|
export interface Item<T> extends Component<any> {
|
|
5
6
|
focus: (options?: FocusOptions) => void,
|
|
@@ -66,6 +67,11 @@ export type BasicProps<T extends Item<U>, U> = {
|
|
|
66
67
|
*/
|
|
67
68
|
fastFocusingOptimization?: boolean,
|
|
68
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Returns a reference to the custom HTML div for the mrcu arrows.
|
|
72
|
+
*/
|
|
73
|
+
mrcuMountingPoint?: Reference<HTMLDivElement>,
|
|
74
|
+
|
|
69
75
|
/**
|
|
70
76
|
* Function called every time before list performs one full scroll.
|
|
71
77
|
* @param item Reference to item on current scroll
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, createRef } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { device } from '@24i/bigscreen-sdk/device';
|
|
3
3
|
import { stopEvent } from '@24i/bigscreen-sdk/utils/stopEvent';
|
|
4
|
+
import { getDisplayToggler, DISPLAY_NONE } from '@24i/bigscreen-sdk/utils/displayToggler';
|
|
4
5
|
import { service } from './service';
|
|
5
6
|
import {
|
|
6
7
|
Props,
|
|
@@ -25,6 +26,16 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
25
26
|
*/
|
|
26
27
|
listensToMouse = false;
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Element for triggering menu by mouse event.
|
|
31
|
+
*/
|
|
32
|
+
mouseTriggerElement = createRef<HTMLDivElement>();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* DisplayToggler for {@link mouseTriggerElement}.
|
|
36
|
+
*/
|
|
37
|
+
mouseTriggerElementDisplayToggler = getDisplayToggler(this.mouseTriggerElement, true);
|
|
38
|
+
|
|
28
39
|
/**
|
|
29
40
|
* Adds event listeners:
|
|
30
41
|
* - keydown to {@link Props.elementForEvents elementForEvents}
|
|
@@ -58,10 +69,12 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
58
69
|
onVisibilityChange = (visible: boolean) => {
|
|
59
70
|
if (visible) {
|
|
60
71
|
this.menu.current!.focus();
|
|
72
|
+
if (this.listensToMouse) this.mouseTriggerElementDisplayToggler.hide();
|
|
61
73
|
service.triggerEvent('visibilitychange', true);
|
|
62
74
|
} else {
|
|
63
75
|
const { router: { current: router } } = this.props;
|
|
64
76
|
router!.focus();
|
|
77
|
+
if (this.listensToMouse) this.mouseTriggerElementDisplayToggler.show();
|
|
65
78
|
service.triggerEvent('visibilitychange', false);
|
|
66
79
|
}
|
|
67
80
|
};
|
|
@@ -88,14 +101,10 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
88
101
|
* @param event mouse event
|
|
89
102
|
*/
|
|
90
103
|
onMouseMove = (event: MouseEvent) => {
|
|
91
|
-
const { Menu } = this.props;
|
|
92
104
|
const menu = this.menu.current!;
|
|
93
105
|
if (this.isMenuAvailable() && !menu.isOpen()) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
menu.open();
|
|
97
|
-
stopEvent(event);
|
|
98
|
-
}
|
|
106
|
+
menu.open();
|
|
107
|
+
stopEvent(event);
|
|
99
108
|
}
|
|
100
109
|
};
|
|
101
110
|
|
|
@@ -127,8 +136,8 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
127
136
|
addMouseListener() {
|
|
128
137
|
if (!this.listensToMouse) {
|
|
129
138
|
this.listensToMouse = true;
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
if (!this.menu.current!.isOpen()) this.mouseTriggerElementDisplayToggler.show();
|
|
140
|
+
this.mouseTriggerElement.current!.addEventListener('mousemove', this.onMouseMove);
|
|
132
141
|
}
|
|
133
142
|
}
|
|
134
143
|
|
|
@@ -138,8 +147,8 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
138
147
|
removeMouseListener() {
|
|
139
148
|
if (this.listensToMouse) {
|
|
140
149
|
this.listensToMouse = false;
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
if (!this.menu.current!.isOpen()) this.mouseTriggerElementDisplayToggler.hide();
|
|
151
|
+
this.mouseTriggerElement.current!.removeEventListener('mousemove', this.onMouseMove);
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
154
|
|
|
@@ -155,12 +164,18 @@ export class MenuAndContentContainer<T extends string = string>
|
|
|
155
164
|
const { children, items, Menu } = this.props;
|
|
156
165
|
return (
|
|
157
166
|
<>
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
<div className="menu-container">
|
|
168
|
+
<Menu
|
|
169
|
+
ref={this.menu}
|
|
170
|
+
items={items}
|
|
171
|
+
onVisibilityChange={this.onVisibilityChange}
|
|
172
|
+
contentContainer={this}
|
|
173
|
+
/>
|
|
174
|
+
<div
|
|
175
|
+
ref={this.mouseTriggerElement}
|
|
176
|
+
className={`menu-mouse-trigger ${DISPLAY_NONE}`}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
164
179
|
{children}
|
|
165
180
|
</>
|
|
166
181
|
);
|
|
@@ -119,13 +119,6 @@ export interface Menu<
|
|
|
119
119
|
updateItems(items: MenuItem<T>[]): void,
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* Function for deciding whether to open menu based on mouse position.
|
|
124
|
-
*/
|
|
125
|
-
type MouseMenuOpenResolver = (
|
|
126
|
-
({ clientX, clientY }: { clientX: number, clientY: number }) => boolean
|
|
127
|
-
);
|
|
128
|
-
|
|
129
122
|
/**
|
|
130
123
|
* Function for deciding whether to open menu based on pressed key.
|
|
131
124
|
*/
|
|
@@ -145,7 +138,6 @@ type KeyboardMenuCloseResolver = (
|
|
|
145
138
|
*/
|
|
146
139
|
export interface MenuComponent<T extends string = string, P extends MenuProps<T> = MenuProps<T>> {
|
|
147
140
|
new (props: P): Menu<T, P>,
|
|
148
|
-
shouldOpenMenuWithMouse: MouseMenuOpenResolver,
|
|
149
141
|
shouldOpenMenu: KeyboardMenuOpenResolver,
|
|
150
142
|
shouldCloseMenu: KeyboardMenuCloseResolver,
|
|
151
143
|
}
|
|
@@ -220,7 +220,7 @@ export class SideMenu extends Component<Props> implements ISideMenu {
|
|
|
220
220
|
render() {
|
|
221
221
|
const { items } = this.props;
|
|
222
222
|
return (
|
|
223
|
-
<div ref={this.visualController.div} className={`menu
|
|
223
|
+
<div ref={this.visualController.div} className={`side-menu ${DISPLAY_NONE}`}>
|
|
224
224
|
<div
|
|
225
225
|
ref={this.visualController.overlay}
|
|
226
226
|
className={`overlay ${animated ? DISPLAY_NONE : ''}`}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
@import '@24i/bigscreen-sdk/sass-utils/transition';
|
|
3
3
|
@import '@24i/bigscreen-sdk/sass-utils/prefix-property';
|
|
4
4
|
|
|
5
|
-
.menu-container {
|
|
5
|
+
.menu-container .side-menu {
|
|
6
6
|
@include transform(translate3d(0, 0, 0));
|
|
7
7
|
@include transition(prefix-property(transform), 300ms);
|
|
8
8
|
|
|
@@ -36,7 +36,9 @@ export class ModalService extends Component<Props> {
|
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
getMountedComponent() {
|
|
39
|
+
getMountedComponent() {
|
|
40
|
+
return this.modalRef;
|
|
41
|
+
}
|
|
40
42
|
|
|
41
43
|
open<T extends IModal>(render: (ref: Reference<T>) => JSX.Element) {
|
|
42
44
|
const { isFocusable } = this.props;
|
|
@@ -94,6 +94,22 @@ export class MouseNavigation extends Component<Props> {
|
|
|
94
94
|
}
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
+
onWheel = (event: WheelEvent) => {
|
|
98
|
+
const { forward, backward, direction } = this.props;
|
|
99
|
+
const { horizontal } = this.mapDirectionToProps(direction);
|
|
100
|
+
if (horizontal) return;
|
|
101
|
+
if (event.deltaY > 0) forward();
|
|
102
|
+
else if (event.deltaY < 0) backward();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
addWheelListner() {
|
|
106
|
+
this.arrows.current?.domRef.current?.addEventListener('wheel', this.onWheel);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
removeWheelListner() {
|
|
110
|
+
this.arrows.current?.domRef.current?.removeEventListener('wheel', this.onWheel);
|
|
111
|
+
}
|
|
112
|
+
|
|
97
113
|
isActive() {
|
|
98
114
|
return this.navigationState === 'active';
|
|
99
115
|
}
|
|
@@ -112,6 +128,7 @@ export class MouseNavigation extends Component<Props> {
|
|
|
112
128
|
getMountingPoint(),
|
|
113
129
|
);
|
|
114
130
|
this.handleArrowState();
|
|
131
|
+
this.addWheelListner();
|
|
115
132
|
this.navigationState = 'active';
|
|
116
133
|
};
|
|
117
134
|
|
|
@@ -129,6 +146,7 @@ export class MouseNavigation extends Component<Props> {
|
|
|
129
146
|
destroyArrows() {
|
|
130
147
|
if (this.navigationState === 'inactive') return;
|
|
131
148
|
this.navigationState = 'inactive';
|
|
149
|
+
this.removeWheelListner();
|
|
132
150
|
removeNode(this.arrows.current!.domRef);
|
|
133
151
|
}
|
|
134
152
|
|
|
@@ -189,11 +189,7 @@ export class PlayerUI extends Component<Props>
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
canHideAutomatically() {
|
|
192
|
-
return
|
|
193
|
-
this.isPlaying()
|
|
194
|
-
&& !this.seeking.isSeeking()
|
|
195
|
-
&& !this.isHidingDisabled
|
|
196
|
-
);
|
|
192
|
+
return !this.isHidingDisabled;
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
isPlaying() {
|
|
@@ -1273,7 +1273,6 @@ declare namespace React {
|
|
|
1273
1273
|
shiftKey: boolean;
|
|
1274
1274
|
/** @deprecated */
|
|
1275
1275
|
which: number;
|
|
1276
|
-
target: EventTarget & T;
|
|
1277
1276
|
}
|
|
1278
1277
|
|
|
1279
1278
|
interface MouseEvent<T = Element, E = NativeMouseEvent> extends UIEvent<T, E> {
|
|
@@ -2144,6 +2143,7 @@ declare namespace React {
|
|
|
2144
2143
|
name?: string | undefined;
|
|
2145
2144
|
noValidate?: boolean | undefined;
|
|
2146
2145
|
target?: string | undefined;
|
|
2146
|
+
rel?: string | undefined;
|
|
2147
2147
|
}
|
|
2148
2148
|
|
|
2149
2149
|
interface HtmlHTMLAttributes<T> extends HTMLAttributes<T> {
|
|
@@ -42,6 +42,8 @@ export const createCounter = ({ triggerAt, callback }: CounterProps): ICounter =
|
|
|
42
42
|
getCurrentValue: () => counter,
|
|
43
43
|
isTriggered: () => counter >= triggerAt,
|
|
44
44
|
isEqual: (value: number = triggerAt) => counter === value,
|
|
45
|
-
reset: () => {
|
|
45
|
+
reset: () => {
|
|
46
|
+
counter = 0;
|
|
47
|
+
},
|
|
46
48
|
};
|
|
47
49
|
};
|
|
@@ -32,8 +32,8 @@ export type ShouldRetryParam = {
|
|
|
32
32
|
function shouldRetryRequest(data: ShouldRetryParam) {
|
|
33
33
|
const { error, response } = data;
|
|
34
34
|
if (error) return true;
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
return !response || !response.ok;
|
|
36
|
+
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export const defaultRetryConfig = {
|
|
@@ -12,7 +12,11 @@ export class VolumeControlUIMock extends Component<{}> implements IVolumeControl
|
|
|
12
12
|
|
|
13
13
|
hide = () => {};
|
|
14
14
|
|
|
15
|
-
isVisible() {
|
|
15
|
+
isVisible() {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
16
18
|
|
|
17
|
-
render() {
|
|
19
|
+
render() {
|
|
20
|
+
return <div className="volume-control-ui" />;
|
|
21
|
+
}
|
|
18
22
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { createRef, forwardRef, Reference } from '@24i/bigscreen-sdk/jsx';
|
|
2
|
-
import { MouseNavigation } from '@24i/bigscreen-sdk/mouse-navigation';
|
|
3
|
-
import { GridBase as Base, Props as GridProps } from './Base';
|
|
4
|
-
import { Item } from '../types';
|
|
5
|
-
|
|
6
|
-
export const GridBase = forwardRef(<T extends Item<U>, U>(props: GridProps<T, U>,
|
|
7
|
-
gridRef: Reference<Base<T, U>>,
|
|
8
|
-
) => {
|
|
9
|
-
const direction = props.horizontal ? 'horizontal' : 'vertical';
|
|
10
|
-
const mrcuRef = createRef<MouseNavigation>();
|
|
11
|
-
return (
|
|
12
|
-
<MouseNavigation
|
|
13
|
-
ref={mrcuRef}
|
|
14
|
-
getMountingPoint={() => gridRef.current!.scroller.current!.wrapRef}
|
|
15
|
-
direction={direction}
|
|
16
|
-
forward={props.mrcuForward || props.forwardGroup}
|
|
17
|
-
backward={props.mrcuBackward || props.backwardGroup}
|
|
18
|
-
shouldShowMrcuForward={props.shouldShowMrcuForward}
|
|
19
|
-
shouldShowMrcuBackward={props.shouldShowMrcuBackward}
|
|
20
|
-
>
|
|
21
|
-
<Base {...props} ref={gridRef} mrcuRef={mrcuRef} />
|
|
22
|
-
</MouseNavigation>
|
|
23
|
-
);
|
|
24
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GridBase } from './Base.mouse';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GridBase } from './Base.mouse';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GridBase } from './Base.mouse';
|