@applicaster/zapp-react-dom-app 12.0.0-rc.75 → 12.0.0-rc.76

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.
@@ -31,14 +31,23 @@ import {
31
31
  import { PlayerContentContext } from "@applicaster/zapp-react-dom-ui-components/Contexts";
32
32
 
33
33
  import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator";
34
- import { Platform } from "react-native";
35
34
  import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
36
35
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
37
36
  import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
37
+ import {
38
+ isVizioPlatform,
39
+ isSamsungPlatform,
40
+ isLgPlatform,
41
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
42
+
43
+ import { OnScreenKeyboard } from "@applicaster/zapp-react-dom-ui-components/Components/OnScreenKeyboard";
38
44
 
39
45
  const { withXray } = getXray();
40
46
  const globalAny: any = global;
41
47
 
48
+ const shouldUseOnScreenKeyboard = () =>
49
+ isVizioPlatform() || window.applicaster.useOnScreenKeyboard;
50
+
42
51
  type Props = {
43
52
  displayState: string;
44
53
  setDisplayState: (state: string) => void;
@@ -56,7 +65,7 @@ type Props = {
56
65
  };
57
66
  };
58
67
 
59
- type State = { isKeyboardVisible: boolean };
68
+ type State = { isKeyboardVisible: boolean; keyboardInput: string };
60
69
 
61
70
  type KeyCode = { code: string; keyCode: number | string };
62
71
 
@@ -76,6 +85,7 @@ export function withInteractionManager(Component: React.FC) {
76
85
  sequenceTimeout: NodeJS.Timeout | null; // timeoutID
77
86
  userSequence: number[] = [];
78
87
  confirmDialog: any;
88
+ isDismissing = false;
79
89
 
80
90
  constructor(props) {
81
91
  super(props);
@@ -84,6 +94,7 @@ export function withInteractionManager(Component: React.FC) {
84
94
 
85
95
  this.state = {
86
96
  isKeyboardVisible: false,
97
+ keyboardInput: "",
87
98
  };
88
99
 
89
100
  this.onMouseMoveListener = debounce({
@@ -116,6 +127,10 @@ export function withInteractionManager(Component: React.FC) {
116
127
  this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
117
128
  this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
118
129
  this.performExit = this.performExit.bind(this);
130
+ this.handleInputFocus = this.handleInputFocus.bind(this);
131
+ this.handleInputBlur = this.handleInputBlur.bind(this);
132
+ this.handleKeyboardInput = this.handleKeyboardInput.bind(this);
133
+ this.handleKeyboardDismiss = this.handleKeyboardDismiss.bind(this);
119
134
 
120
135
  this.confirmDialog.setConfirmAction(this.performExit);
121
136
  this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
@@ -138,6 +153,8 @@ export function withInteractionManager(Component: React.FC) {
138
153
  false
139
154
  );
140
155
 
156
+ document.addEventListener("focusin", this.handleInputFocus);
157
+
141
158
  document.addEventListener(
142
159
  "cursorStateChange",
143
160
  this.cursorVisibilityChange,
@@ -155,28 +172,31 @@ export function withInteractionManager(Component: React.FC) {
155
172
  this.cursorVisibilityChange
156
173
  );
157
174
 
158
- document.removeEventListener(
159
- "keyboardStateChange",
160
- this.onKeyboardStateChange
161
- );
175
+ document.removeEventListener("focusin", this.handleInputFocus);
162
176
 
163
177
  document.removeEventListener("mousedown", this.onMouseDownListener);
164
178
 
165
179
  if (this.timeout) {
166
180
  this.clearTimeout();
167
181
  }
182
+
183
+ this.isDismissing = false;
168
184
  }
169
185
 
170
186
  performExit() {
171
- if (Platform.OS === ("samsung_tv" as QuickBrickPlatforms)) {
187
+ if (isSamsungPlatform()) {
172
188
  this.onConfirmDialogClose();
173
189
  sendQuickBrickEvent(QUICK_BRICK_EVENTS.MOVE_APP_TO_BACKGROUND);
174
190
  }
175
191
 
176
- if (Platform.OS === ("lg_tv" as QuickBrickPlatforms)) {
192
+ if (isLgPlatform()) {
177
193
  // webOS recommend to use this method when implemention a custom exit
178
194
  globalAny.close();
179
195
  }
196
+
197
+ if (isVizioPlatform()) {
198
+ window?.VIZIO?.exitApplication();
199
+ }
180
200
  }
181
201
 
182
202
  handleWebOsBack() {
@@ -205,7 +225,7 @@ export function withInteractionManager(Component: React.FC) {
205
225
  platformBack() {
206
226
  try {
207
227
  // TODO: temporary hack until this code is refactored
208
- if (Platform.OS === ("samsung_tv" as QuickBrickPlatforms)) {
228
+ if (isSamsungPlatform() || isVizioPlatform()) {
209
229
  const { isDialogVisible } = confirmationDialogStore.getState();
210
230
 
211
231
  if (isDialogVisible) {
@@ -218,7 +238,7 @@ export function withInteractionManager(Component: React.FC) {
218
238
  cancelCompletion: this.onConfirmDialogClose,
219
239
  });
220
240
  }
221
- } else if (Platform.OS === ("lg_tv" as QuickBrickPlatforms)) {
241
+ } else if (isLgPlatform()) {
222
242
  this.handleWebOsBack();
223
243
  }
224
244
  } catch (e) {
@@ -441,6 +461,7 @@ export function withInteractionManager(Component: React.FC) {
441
461
 
442
462
  onKeyDown(event) {
443
463
  const { displayState, setDisplayState, navigator } = this.props;
464
+ const { isKeyboardVisible } = this.state;
444
465
 
445
466
  const { isDialogVisible } = confirmationDialogStore.getState();
446
467
 
@@ -451,6 +472,16 @@ export function withInteractionManager(Component: React.FC) {
451
472
  }, LONG_KEY_PRESS_TIMEOUT);
452
473
  }
453
474
 
475
+ if (isKeyboardVisible && shouldUseOnScreenKeyboard()) {
476
+ if (keyCode(event).matchesAny("Escape", "Back")) {
477
+ event.preventDefault();
478
+ event.stopPropagation();
479
+ this.handleKeyboardDismiss();
480
+
481
+ return;
482
+ }
483
+ }
484
+
454
485
  /**
455
486
  When the player is displayed, we listen to Native Play / Pause / Stop
456
487
  buttons. Any other key press will display the transport controls
@@ -567,7 +598,7 @@ export function withInteractionManager(Component: React.FC) {
567
598
  }
568
599
 
569
600
  if (keyCode(event).matches(KEYS.Exit)) {
570
- if (Platform.OS === ("samsung_tv" as QuickBrickPlatforms)) {
601
+ if (isSamsungPlatform() || shouldUseOnScreenKeyboard()) {
571
602
  this.performExit();
572
603
 
573
604
  return;
@@ -622,11 +653,9 @@ export function withInteractionManager(Component: React.FC) {
622
653
  };
623
654
 
624
655
  if (deltaY > 0) {
625
- DIRECTION.value =
626
- Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "down" : "up";
656
+ DIRECTION.value = isLgPlatform() ? "down" : "up";
627
657
  } else if (deltaY < 0) {
628
- DIRECTION.value =
629
- Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "up" : "down";
658
+ DIRECTION.value = isLgPlatform() ? "up" : "down";
630
659
  }
631
660
 
632
661
  if (
@@ -667,8 +696,71 @@ export function withInteractionManager(Component: React.FC) {
667
696
  focusManager.setInitialFocus();
668
697
  }
669
698
 
699
+ handleInputFocus = (event: FocusEvent) => {
700
+ if (!shouldUseOnScreenKeyboard()) return;
701
+ const target = event.target as HTMLElement;
702
+
703
+ if (this.isDismissing) {
704
+ return;
705
+ }
706
+
707
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
708
+ this.setState({
709
+ isKeyboardVisible: true,
710
+ keyboardInput: (target as HTMLInputElement).value || "",
711
+ });
712
+ }
713
+ };
714
+
715
+ handleInputBlur(event: FocusEvent) {
716
+ if (!shouldUseOnScreenKeyboard()) return;
717
+
718
+ const target = event.target as HTMLElement;
719
+
720
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
721
+ const relatedTarget = event.relatedTarget as HTMLElement;
722
+
723
+ if (
724
+ !relatedTarget ||
725
+ (relatedTarget.tagName !== "INPUT" &&
726
+ relatedTarget.tagName !== "TEXTAREA")
727
+ ) {
728
+ this.setState({ isKeyboardVisible: false });
729
+ }
730
+ }
731
+ }
732
+
733
+ handleKeyboardDismiss = () => {
734
+ this.isDismissing = true;
735
+
736
+ this.setState(
737
+ {
738
+ isKeyboardVisible: false,
739
+ keyboardInput: "",
740
+ },
741
+ () => {
742
+ this.isDismissing = false;
743
+ }
744
+ );
745
+ };
746
+
747
+ handleKeyboardInput(value: string) {
748
+ this.setState({ keyboardInput: value });
749
+ }
750
+
670
751
  render() {
671
- return <Component {...this.props} />;
752
+ return (
753
+ <>
754
+ <Component {...this.props} />
755
+ {shouldUseOnScreenKeyboard() && this.state.isKeyboardVisible && (
756
+ <OnScreenKeyboard
757
+ initialValue={this.state.keyboardInput}
758
+ onInput={this.handleKeyboardInput}
759
+ onDismiss={this.handleKeyboardDismiss}
760
+ />
761
+ )}
762
+ </>
763
+ );
672
764
  }
673
765
  }
674
766
 
@@ -62,6 +62,9 @@ export const PLATFORMS = {
62
62
  iphone: "iPhone",
63
63
  android: "Android",
64
64
  mobile: "Mobile",
65
+ vizio: "VIZIO",
66
+ smartcast: "SmartCast",
67
+ conjure: "Conjure",
65
68
  };
66
69
 
67
70
  /**
@@ -42,6 +42,36 @@ export const isSamsungPlatform = () => {
42
42
  );
43
43
  };
44
44
 
45
+ /**
46
+ * Checks if we are on the Vizio platform by using the userAgent string
47
+ *
48
+ * Use this method when you need to identify the platform on runtime
49
+ * before the VIZIO Companion Library has loaded
50
+ */
51
+ export const isVizioPlatform = () => {
52
+ const userAgent = getUserAgent();
53
+
54
+ const isVizioAgent =
55
+ userAgent.includes(PLATFORMS.vizio) ||
56
+ userAgent.includes(PLATFORMS.smartcast) ||
57
+ userAgent.includes(PLATFORMS.conjure);
58
+
59
+ return isVizioAgent;
60
+ };
61
+
62
+ /**
63
+ * Checks if we are on the Vizio platform by checking for the global VIZIO object
64
+ * and the VIZIO Companion Library. This method does not use the userAgent string,
65
+ * because it mainly checks whether we have access to apis, which may not be available yet
66
+ */
67
+ export const hasVizioAPIs = () => {
68
+ const hasAPIs =
69
+ typeof window.VIZIO !== "undefined" &&
70
+ window?.applicaster?.vizioLibraryDidLoad;
71
+
72
+ return hasAPIs;
73
+ };
74
+
45
75
  /**
46
76
  * platformSelect can't be used, because Platform.OS is overriden
47
77
  * by overloadReactNativePlatform and don't support 'web' value
@@ -253,6 +283,24 @@ export const getDeviceData = async () => {
253
283
  ...tizenConnectionInfo,
254
284
  device_type: getDeviceType(),
255
285
  };
286
+ } else if (isVizioPlatform()) {
287
+ deviceData = {
288
+ ...deviceData,
289
+ platform: "vizio",
290
+ deviceMake: "Vizio",
291
+ deviceType: "tv",
292
+ userAgent: getUserAgent(),
293
+ deviceWidth: window.innerWidth,
294
+ deviceHeight: window.innerHeight,
295
+ };
296
+
297
+ if (hasVizioAPIs()) {
298
+ window.VIZIO.getFirmwareVersion(function (firmwareVersion) {
299
+ deviceData.osVersion = firmwareVersion;
300
+ });
301
+
302
+ deviceData.deviceModel = window.VIZIO.deviceModel;
303
+ }
256
304
  }
257
305
 
258
306
  return deviceData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-dom-app",
3
- "version": "12.0.0-rc.75",
3
+ "version": "12.0.0-rc.76",
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.75",
26
- "@applicaster/zapp-react-native-bridge": "12.0.0-rc.75",
27
- "@applicaster/zapp-react-native-redux": "12.0.0-rc.75",
28
- "@applicaster/zapp-react-native-ui-components": "12.0.0-rc.75",
29
- "@applicaster/zapp-react-native-utils": "12.0.0-rc.75",
25
+ "@applicaster/zapp-react-dom-ui-components": "12.0.0-rc.76",
26
+ "@applicaster/zapp-react-native-bridge": "12.0.0-rc.76",
27
+ "@applicaster/zapp-react-native-redux": "12.0.0-rc.76",
28
+ "@applicaster/zapp-react-native-ui-components": "12.0.0-rc.76",
29
+ "@applicaster/zapp-react-native-utils": "12.0.0-rc.76",
30
30
  "abortcontroller-polyfill": "^1.7.5",
31
31
  "history": "^4.7.2",
32
32
  "react-router-dom": "^5.1.2",