@applicaster/zapp-react-dom-app 12.0.0-rc.122 → 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.
@@ -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
- import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
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
- longKeyPressTimeout: any | null;
88
- longPressActive: boolean;
89
- timeout: any | null;
90
- sequenceTimeout: NodeJS.Timeout | null; // timeoutID
91
- userSequence: number[] = [];
92
- confirmDialog: any;
93
- isDismissing = false;
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.longKeyPressTimeout = null;
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
- clearLongPressTimeout() {
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
- if (this.longPressActive) {
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.longKeyPressTimeout = setTimeout(() => {
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 (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
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.122",
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.122",
26
- "@applicaster/zapp-react-native-bridge": "12.0.0-rc.122",
27
- "@applicaster/zapp-react-native-redux": "12.0.0-rc.122",
28
- "@applicaster/zapp-react-native-ui-components": "12.0.0-rc.122",
29
- "@applicaster/zapp-react-native-utils": "12.0.0-rc.122",
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",