@applicaster/zapp-react-dom-app 12.0.0-rc.123 → 12.0.0-rc.124
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/App/InteractionManager/index.tsx +143 -169
- package/package.json +6 -6
|
@@ -33,9 +33,13 @@ import {
|
|
|
33
33
|
import { PlayerContentContext } from "@applicaster/zapp-react-dom-ui-components/Contexts";
|
|
34
34
|
|
|
35
35
|
import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator";
|
|
36
|
-
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
37
36
|
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
|
|
38
|
-
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
confirmationDialogStore,
|
|
40
|
+
ConfirmationDialogState,
|
|
41
|
+
} from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
|
|
42
|
+
|
|
39
43
|
import {
|
|
40
44
|
isLgPlatform,
|
|
41
45
|
isSamsungPlatform,
|
|
@@ -43,6 +47,7 @@ import {
|
|
|
43
47
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
44
48
|
|
|
45
49
|
import { OnScreenKeyboard } from "@applicaster/zapp-react-dom-ui-components/Components/OnScreenKeyboard";
|
|
50
|
+
import { KeyboardLongPressManager } from "@applicaster/zapp-react-dom-ui-components/Utils/KeyboardLongPressManager";
|
|
46
51
|
|
|
47
52
|
const { withXray } = getXray();
|
|
48
53
|
const globalAny: any = global;
|
|
@@ -65,6 +70,7 @@ type Props = {
|
|
|
65
70
|
onRewindPressOut: () => void;
|
|
66
71
|
onForwardPressOut: () => void;
|
|
67
72
|
};
|
|
73
|
+
confirmDialog: typeof confirmationDialogStore;
|
|
68
74
|
};
|
|
69
75
|
|
|
70
76
|
interface State {
|
|
@@ -84,25 +90,24 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
84
90
|
onMouseMoveListener: (event: MouseEvent) => void;
|
|
85
91
|
onScrollListener: (event: MouseEvent) => void;
|
|
86
92
|
|
|
87
|
-
|
|
88
|
-
longPressActive: boolean;
|
|
89
|
-
timeout: any | null;
|
|
90
|
-
sequenceTimeout: NodeJS.Timeout | null;
|
|
91
|
-
userSequence: number[] = [];
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
private longPressDetector: KeyboardLongPressManager;
|
|
94
|
+
private longPressActive: boolean = false;
|
|
95
|
+
private timeout: any | null = null;
|
|
96
|
+
private sequenceTimeout: NodeJS.Timeout | null;
|
|
97
|
+
private userSequence: number[] = [];
|
|
98
|
+
private isDismissing = false;
|
|
99
|
+
private confirmDialog: ConfirmationDialogState =
|
|
100
|
+
confirmationDialogStore.getState();
|
|
101
|
+
|
|
102
|
+
state: State = {
|
|
103
|
+
isKeyboardVisible: false,
|
|
104
|
+
keyboardInput: "",
|
|
105
|
+
activeInputRef: null,
|
|
106
|
+
};
|
|
94
107
|
|
|
95
108
|
constructor(props) {
|
|
96
109
|
super(props);
|
|
97
110
|
|
|
98
|
-
this.onKeyDownListener = this.onKeyDown.bind(this);
|
|
99
|
-
|
|
100
|
-
this.state = {
|
|
101
|
-
isKeyboardVisible: false,
|
|
102
|
-
keyboardInput: "",
|
|
103
|
-
activeInputRef: null,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
111
|
this.onMouseMoveListener = debounce({
|
|
107
112
|
fn: this.onMouseMove,
|
|
108
113
|
context: this,
|
|
@@ -119,9 +124,7 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
119
124
|
context: this,
|
|
120
125
|
});
|
|
121
126
|
|
|
122
|
-
this.
|
|
123
|
-
this.longPressActive = false;
|
|
124
|
-
this.confirmDialog = confirmationDialogStore.getState();
|
|
127
|
+
this.onKeyDownListener = this.onKeyDown.bind(this);
|
|
125
128
|
this.resetHudTimeout = this.resetHudTimeout.bind(this);
|
|
126
129
|
this.cursorVisibilityChange = this.cursorVisibilityChange.bind(this);
|
|
127
130
|
this.onKeyDown = this.onKeyDown.bind(this);
|
|
@@ -137,9 +140,18 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
137
140
|
this.handleInputBlur = this.handleInputBlur.bind(this);
|
|
138
141
|
this.handleKeyboardInput = this.handleKeyboardInput.bind(this);
|
|
139
142
|
this.handleKeyboardDismiss = this.handleKeyboardDismiss.bind(this);
|
|
143
|
+
this.onKeyDownListener = this.onKeyDown.bind(this);
|
|
144
|
+
this.onKeyUp = this.onKeyUp.bind(this);
|
|
145
|
+
this.onMouseMoveListener = this.onMouseMove.bind(this);
|
|
146
|
+
this.onScrollListener = this.onScroll.bind(this);
|
|
147
|
+
this.onMouseDownListener = this.onMouseDown.bind(this);
|
|
148
|
+
this.onKeyboardStateChange = this.onKeyboardStateChange.bind(this);
|
|
149
|
+
this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
|
|
150
|
+
this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
|
|
140
151
|
|
|
141
152
|
this.confirmDialog.setConfirmAction(this.performExit);
|
|
142
153
|
this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
|
|
154
|
+
this.longPressDetector = new KeyboardLongPressManager();
|
|
143
155
|
}
|
|
144
156
|
|
|
145
157
|
componentDidMount() {
|
|
@@ -166,6 +178,13 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
166
178
|
this.cursorVisibilityChange,
|
|
167
179
|
false
|
|
168
180
|
);
|
|
181
|
+
|
|
182
|
+
window.addEventListener("onLongPress", this.handleLongPress.bind(this));
|
|
183
|
+
|
|
184
|
+
window.addEventListener(
|
|
185
|
+
"onLongPressRelease",
|
|
186
|
+
this.handleLongPressRelease.bind(this)
|
|
187
|
+
);
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
componentWillUnmount() {
|
|
@@ -187,6 +206,13 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
187
206
|
}
|
|
188
207
|
|
|
189
208
|
this.isDismissing = false;
|
|
209
|
+
this.longPressDetector.cleanup();
|
|
210
|
+
window.removeEventListener("onLongPress", this.handleLongPress);
|
|
211
|
+
|
|
212
|
+
window.removeEventListener(
|
|
213
|
+
"onLongPressRelease",
|
|
214
|
+
this.handleLongPressRelease
|
|
215
|
+
);
|
|
190
216
|
}
|
|
191
217
|
|
|
192
218
|
performExit() {
|
|
@@ -308,155 +334,13 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
308
334
|
}
|
|
309
335
|
}
|
|
310
336
|
|
|
311
|
-
|
|
312
|
-
if (this.longKeyPressTimeout) {
|
|
313
|
-
clearTimeout(this.longKeyPressTimeout);
|
|
314
|
-
this.longKeyPressTimeout = null;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* If the keySupportsLongPress this method is called on longpress of key
|
|
320
|
-
* Register your longpress handlers here, and make sure to add it to list of supported keys
|
|
321
|
-
*/
|
|
322
|
-
onLongPress(event) {
|
|
323
|
-
this.longPressActive = true;
|
|
324
|
-
// Legacy way of determining whether controls are being displayed
|
|
325
|
-
// Or if the player is in a playback state.
|
|
326
|
-
const { displayState } = this.props;
|
|
327
|
-
const playerState = displayState === DISPLAY_STATES.PLAYER;
|
|
328
|
-
const hudState = displayState === DISPLAY_STATES.HUD;
|
|
329
|
-
const playbackState = playerState || hudState;
|
|
330
|
-
|
|
331
|
-
switch (event.code) {
|
|
332
|
-
case KEYS.Back.code:
|
|
333
|
-
// If you longpress the back button we probably want to exit
|
|
334
|
-
this.platformBack();
|
|
335
|
-
|
|
336
|
-
break;
|
|
337
|
-
|
|
338
|
-
case KEYS.Enter.code:
|
|
339
|
-
focusManager.longPress();
|
|
340
|
-
|
|
341
|
-
break;
|
|
342
|
-
|
|
343
|
-
case KEYS.Forward.code:
|
|
344
|
-
playbackState && this.props.seekMethods.onForwardLongPress();
|
|
345
|
-
|
|
346
|
-
break;
|
|
347
|
-
|
|
348
|
-
case KEYS.Rewind.code:
|
|
349
|
-
playbackState && this.props.seekMethods.onRewindLongPress();
|
|
350
|
-
|
|
351
|
-
break;
|
|
352
|
-
|
|
353
|
-
default:
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* If the keySupportsLongPress this method is called on keyup of a longpress key
|
|
360
|
-
* If you need to handle the release or keyup of a longpress key register the handler here
|
|
361
|
-
*/
|
|
362
|
-
onLongPressRelease(event) {
|
|
363
|
-
this.longPressActive = false;
|
|
337
|
+
cancelHudTimeout() {
|
|
364
338
|
this.resetHudTimeout();
|
|
365
|
-
|
|
366
|
-
focusManager.pressOut();
|
|
367
|
-
|
|
368
|
-
switch (event.code) {
|
|
369
|
-
case KEYS.Forward.code:
|
|
370
|
-
this.props.seekMethods.onForwardPressOut();
|
|
371
|
-
|
|
372
|
-
break;
|
|
373
|
-
|
|
374
|
-
case KEYS.Rewind.code:
|
|
375
|
-
this.props.seekMethods.onForwardPressOut();
|
|
376
|
-
|
|
377
|
-
break;
|
|
378
|
-
|
|
379
|
-
default:
|
|
380
|
-
break;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Resets the sequence of keys we captured.
|
|
386
|
-
* Clear ensures that we don't interpret regular interactions
|
|
387
|
-
* as a sequence used to unlock certain features
|
|
388
|
-
*/
|
|
389
|
-
resetSequenceTimeout() {
|
|
390
|
-
const SEQUENCE_ENTRY_TIME = 1900;
|
|
391
|
-
|
|
392
|
-
if (this.sequenceTimeout) {
|
|
393
|
-
// Start timer over
|
|
394
|
-
clearTimeout(this.sequenceTimeout);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
this.sequenceTimeout = setTimeout(() => {
|
|
398
|
-
// User needs to complete sequence before SEQUENCE_ENTRY_TIME
|
|
399
|
-
// or we set userSequence, and prev sequenceTimeout to empty values
|
|
400
|
-
this.sequenceTimeout = null;
|
|
401
|
-
this.userSequence = [];
|
|
402
|
-
}, SEQUENCE_ENTRY_TIME);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* If a certain sequence of keys are pressed we enable special menus or settings
|
|
407
|
-
* Each supported sequence can be stored as a constant
|
|
408
|
-
*/
|
|
409
|
-
checkSequence(key) {
|
|
410
|
-
const SINK_SEQUENCE = [
|
|
411
|
-
KEYS.ArrowUp.keyCode,
|
|
412
|
-
KEYS.ArrowUp.keyCode,
|
|
413
|
-
KEYS.ArrowDown.keyCode,
|
|
414
|
-
KEYS.ArrowDown.keyCode,
|
|
415
|
-
KEYS.ArrowLeft.keyCode,
|
|
416
|
-
KEYS.ArrowRight.keyCode,
|
|
417
|
-
KEYS.ArrowLeft.keyCode,
|
|
418
|
-
KEYS.ArrowRight.keyCode,
|
|
419
|
-
];
|
|
420
|
-
|
|
421
|
-
this.resetSequenceTimeout();
|
|
422
|
-
this.userSequence.push(key);
|
|
423
|
-
|
|
424
|
-
// Remember [1,2,3] !== [1,2,3] in js, so string comparison is better
|
|
425
|
-
const shouldAddSink =
|
|
426
|
-
this.userSequence.toString() === SINK_SEQUENCE.toString();
|
|
427
|
-
|
|
428
|
-
if (shouldAddSink) {
|
|
429
|
-
this.props.xray.addRemoteSink({});
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Determines whether the key supports or handles longpress
|
|
435
|
-
* At the moment the only keys that support are the ones defined in
|
|
436
|
-
* supportedEvents array. This logic just prevents us from registering timeouts for every key
|
|
437
|
-
*/
|
|
438
|
-
keySupportsLongPress(event): boolean {
|
|
439
|
-
const supportedEvents = [KEYS.Back, KEYS.Enter, KEYS.Rewind, KEYS.Forward];
|
|
440
|
-
|
|
441
|
-
const eventMatcher = R.compose(R.prop("matches"), keyCode)(event);
|
|
442
|
-
|
|
443
|
-
const supportsLongPress = R.compose(
|
|
444
|
-
R.any(R.equals(true)),
|
|
445
|
-
R.map(eventMatcher)
|
|
446
|
-
)(supportedEvents);
|
|
447
|
-
|
|
448
|
-
return supportsLongPress;
|
|
449
339
|
}
|
|
450
340
|
|
|
451
341
|
onKeyUp(event: KeyboardEvent) {
|
|
452
|
-
// If this is a supported longpress key we need to clear the timeout and handle release of key
|
|
453
|
-
// This logic is handled by onLongPressRelease
|
|
454
342
|
if (this.keySupportsLongPress(event)) {
|
|
455
|
-
|
|
456
|
-
this.onLongPressRelease(event);
|
|
457
|
-
} else {
|
|
458
|
-
this.clearLongPressTimeout();
|
|
459
|
-
}
|
|
343
|
+
this.longPressDetector.endKeyPressMonitoring(event.code);
|
|
460
344
|
}
|
|
461
345
|
}
|
|
462
346
|
|
|
@@ -477,13 +361,13 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
477
361
|
return;
|
|
478
362
|
}
|
|
479
363
|
|
|
480
|
-
// If this is a supported longpress key we need to set the timeout and handle the longpress
|
|
481
364
|
if (this.keySupportsLongPress(event)) {
|
|
482
|
-
this.
|
|
483
|
-
this.onLongPress(event);
|
|
484
|
-
}, LONG_KEY_PRESS_TIMEOUT);
|
|
365
|
+
this.longPressDetector.monitorKeyPress(event.code, event);
|
|
485
366
|
}
|
|
486
367
|
|
|
368
|
+
// None of the logic below should be executed for repeated keys
|
|
369
|
+
if (event.repeat) return;
|
|
370
|
+
|
|
487
371
|
/**
|
|
488
372
|
When the player is displayed, we listen to Native Play / Pause / Stop
|
|
489
373
|
buttons. Any other key press will display the transport controls
|
|
@@ -704,7 +588,10 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
704
588
|
|
|
705
589
|
if (this.isDismissing) return;
|
|
706
590
|
|
|
707
|
-
if (
|
|
591
|
+
if (
|
|
592
|
+
(target.tagName === "INPUT" && target.type === "text") ||
|
|
593
|
+
target.tagName === "TEXTAREA"
|
|
594
|
+
) {
|
|
708
595
|
this.setState({
|
|
709
596
|
isKeyboardVisible: true,
|
|
710
597
|
keyboardInput: target.value || "",
|
|
@@ -764,6 +651,93 @@ class InteractionManagerClass extends React.Component<Props, State> {
|
|
|
764
651
|
this.setState({ keyboardInput: value });
|
|
765
652
|
};
|
|
766
653
|
|
|
654
|
+
// TODO: use RemoteSequenceHandler class
|
|
655
|
+
private checkSequence(key: number) {
|
|
656
|
+
const SINK_SEQUENCE = [
|
|
657
|
+
KEYS.ArrowUp.keyCode,
|
|
658
|
+
KEYS.ArrowUp.keyCode,
|
|
659
|
+
KEYS.ArrowDown.keyCode,
|
|
660
|
+
KEYS.ArrowDown.keyCode,
|
|
661
|
+
KEYS.ArrowLeft.keyCode,
|
|
662
|
+
KEYS.ArrowRight.keyCode,
|
|
663
|
+
KEYS.ArrowLeft.keyCode,
|
|
664
|
+
KEYS.ArrowRight.keyCode,
|
|
665
|
+
];
|
|
666
|
+
|
|
667
|
+
this.resetSequenceTimeout();
|
|
668
|
+
this.userSequence.push(key);
|
|
669
|
+
|
|
670
|
+
const shouldAddSink =
|
|
671
|
+
this.userSequence.toString() === SINK_SEQUENCE.toString();
|
|
672
|
+
|
|
673
|
+
if (shouldAddSink) {
|
|
674
|
+
this.props.xray.addRemoteSink({});
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private resetSequenceTimeout() {
|
|
679
|
+
const SEQUENCE_ENTRY_TIME = 1900;
|
|
680
|
+
|
|
681
|
+
if (this.sequenceTimeout) {
|
|
682
|
+
clearTimeout(this.sequenceTimeout);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
this.sequenceTimeout = setTimeout(() => {
|
|
686
|
+
this.sequenceTimeout = null;
|
|
687
|
+
this.userSequence = [];
|
|
688
|
+
}, SEQUENCE_ENTRY_TIME);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
private handleLongPress = (event: CustomEvent) => {
|
|
692
|
+
const { keyCode } = event.detail;
|
|
693
|
+
const { displayState } = this.props;
|
|
694
|
+
const playerState = displayState === DISPLAY_STATES.PLAYER;
|
|
695
|
+
const hudState = displayState === DISPLAY_STATES.HUD;
|
|
696
|
+
const playbackState = playerState || hudState;
|
|
697
|
+
this.longPressActive = true;
|
|
698
|
+
this.cancelHudTimeout();
|
|
699
|
+
|
|
700
|
+
switch (keyCode) {
|
|
701
|
+
case KEYS.Forward.code:
|
|
702
|
+
playbackState && this.props.seekMethods.onForwardLongPress();
|
|
703
|
+
break;
|
|
704
|
+
|
|
705
|
+
case KEYS.Rewind.code:
|
|
706
|
+
playbackState && this.props.seekMethods.onRewindLongPress();
|
|
707
|
+
break;
|
|
708
|
+
|
|
709
|
+
case KEYS.Enter.code:
|
|
710
|
+
focusManager.longPress();
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
private handleLongPressRelease = (event: CustomEvent) => {
|
|
716
|
+
const { keyCode } = event.detail;
|
|
717
|
+
this.longPressActive = false;
|
|
718
|
+
this.resetHudTimeout();
|
|
719
|
+
|
|
720
|
+
switch (keyCode) {
|
|
721
|
+
case KEYS.Forward.code:
|
|
722
|
+
this.props.seekMethods.onForwardPressOut();
|
|
723
|
+
break;
|
|
724
|
+
|
|
725
|
+
case KEYS.Rewind.code:
|
|
726
|
+
this.props.seekMethods.onRewindPressOut();
|
|
727
|
+
break;
|
|
728
|
+
|
|
729
|
+
case KEYS.Enter.code:
|
|
730
|
+
focusManager.pressOut();
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
private keySupportsLongPress(event: KeyboardEvent): boolean {
|
|
736
|
+
return [KEYS.Forward.code, KEYS.Rewind.code, KEYS.Enter.code].includes(
|
|
737
|
+
event.code
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
767
741
|
render() {
|
|
768
742
|
return (
|
|
769
743
|
(shouldUseOnScreenKeyboard() && this.state.isKeyboardVisible && (
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-dom-app",
|
|
3
|
-
"version": "12.0.0-rc.
|
|
3
|
+
"version": "12.0.0-rc.124",
|
|
4
4
|
"description": "Zapp App Component for Applicaster's Quick Brick React Native App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/applicaster/zapp-react-dom-app#readme",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@applicaster/zapp-react-dom-ui-components": "12.0.0-rc.
|
|
26
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.
|
|
27
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-rc.
|
|
28
|
-
"@applicaster/zapp-react-native-ui-components": "12.0.0-rc.
|
|
29
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-rc.
|
|
25
|
+
"@applicaster/zapp-react-dom-ui-components": "12.0.0-rc.124",
|
|
26
|
+
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.124",
|
|
27
|
+
"@applicaster/zapp-react-native-redux": "12.0.0-rc.124",
|
|
28
|
+
"@applicaster/zapp-react-native-ui-components": "12.0.0-rc.124",
|
|
29
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-rc.124",
|
|
30
30
|
"abortcontroller-polyfill": "^1.7.5",
|
|
31
31
|
"history": "^4.7.2",
|
|
32
32
|
"react-router-dom": "^5.1.2",
|