@applicaster/zapp-react-dom-app 12.0.0-alpha.4802689107 → 12.0.0-alpha.4840257570

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.
@@ -35,10 +35,27 @@ import { Platform } from "react-native";
35
35
  import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
36
36
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
37
37
  import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
38
+ import { hasVizioAPIs, isVizioPlatform } from "../Loader/utils/platform";
39
+
40
+ import { OnScreenKeyboard } from "@applicaster/zapp-react-dom-ui-components/Components/OnScreenKeyboard";
41
+
42
+ declare global {
43
+ interface Window {
44
+ applicaster: {
45
+ useOnScreenKeyboard: boolean;
46
+ };
47
+ VIZIO: {
48
+ exitApplication: () => void;
49
+ };
50
+ }
51
+ }
38
52
 
39
53
  const { withXray } = getXray();
40
54
  const globalAny: any = global;
41
55
 
56
+ const shouldUseOnScreenKeyboard = () =>
57
+ isVizioPlatform() || window.applicaster.useOnScreenKeyboard;
58
+
42
59
  type Props = {
43
60
  displayState: string;
44
61
  setDisplayState: (state: string) => void;
@@ -56,7 +73,7 @@ type Props = {
56
73
  };
57
74
  };
58
75
 
59
- type State = { isKeyboardVisible: boolean };
76
+ type State = { isKeyboardVisible: boolean; keyboardInput: string };
60
77
 
61
78
  type KeyCode = { code: string; keyCode: number | string };
62
79
 
@@ -76,6 +93,7 @@ export function withInteractionManager(Component: React.FC) {
76
93
  sequenceTimeout: NodeJS.Timeout | null; // timeoutID
77
94
  userSequence: number[] = [];
78
95
  confirmDialog: any;
96
+ isDismissing = false;
79
97
 
80
98
  constructor(props) {
81
99
  super(props);
@@ -84,6 +102,7 @@ export function withInteractionManager(Component: React.FC) {
84
102
 
85
103
  this.state = {
86
104
  isKeyboardVisible: false,
105
+ keyboardInput: "",
87
106
  };
88
107
 
89
108
  this.onMouseMoveListener = debounce({
@@ -116,6 +135,10 @@ export function withInteractionManager(Component: React.FC) {
116
135
  this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
117
136
  this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
118
137
  this.performExit = this.performExit.bind(this);
138
+ this.handleInputFocus = this.handleInputFocus.bind(this);
139
+ this.handleInputBlur = this.handleInputBlur.bind(this);
140
+ this.handleKeyboardInput = this.handleKeyboardInput.bind(this);
141
+ this.handleKeyboardDismiss = this.handleKeyboardDismiss.bind(this);
119
142
 
120
143
  this.confirmDialog.setConfirmAction(this.performExit);
121
144
  this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
@@ -138,6 +161,9 @@ export function withInteractionManager(Component: React.FC) {
138
161
  false
139
162
  );
140
163
 
164
+ document.addEventListener("focusin", this.handleInputFocus);
165
+ // document.addEventListener("focusout", this.handleInputBlur);
166
+
141
167
  document.addEventListener(
142
168
  "cursorStateChange",
143
169
  this.cursorVisibilityChange,
@@ -155,16 +181,15 @@ export function withInteractionManager(Component: React.FC) {
155
181
  this.cursorVisibilityChange
156
182
  );
157
183
 
158
- document.removeEventListener(
159
- "keyboardStateChange",
160
- this.onKeyboardStateChange
161
- );
184
+ document.removeEventListener("focusin", this.handleInputFocus);
162
185
 
163
186
  document.removeEventListener("mousedown", this.onMouseDownListener);
164
187
 
165
188
  if (this.timeout) {
166
189
  this.clearTimeout();
167
190
  }
191
+
192
+ this.isDismissing = false;
168
193
  }
169
194
 
170
195
  performExit() {
@@ -177,6 +202,10 @@ export function withInteractionManager(Component: React.FC) {
177
202
  // webOS recommend to use this method when implemention a custom exit
178
203
  globalAny.close();
179
204
  }
205
+
206
+ if (hasVizioAPIs()) {
207
+ window.VIZIO.exitApplication();
208
+ }
180
209
  }
181
210
 
182
211
  handleWebOsBack() {
@@ -205,7 +234,10 @@ export function withInteractionManager(Component: React.FC) {
205
234
  platformBack() {
206
235
  try {
207
236
  // TODO: temporary hack until this code is refactored
208
- if (Platform.OS === ("samsung_tv" as QuickBrickPlatforms)) {
237
+ if (
238
+ Platform.OS === ("samsung_tv" as QuickBrickPlatforms) ||
239
+ hasVizioAPIs()
240
+ ) {
209
241
  const { isDialogVisible } = confirmationDialogStore.getState();
210
242
 
211
243
  if (isDialogVisible) {
@@ -441,6 +473,7 @@ export function withInteractionManager(Component: React.FC) {
441
473
 
442
474
  onKeyDown(event) {
443
475
  const { displayState, setDisplayState, navigator } = this.props;
476
+ const { isKeyboardVisible } = this.state;
444
477
 
445
478
  const { isDialogVisible } = confirmationDialogStore.getState();
446
479
 
@@ -451,6 +484,16 @@ export function withInteractionManager(Component: React.FC) {
451
484
  }, LONG_KEY_PRESS_TIMEOUT);
452
485
  }
453
486
 
487
+ if (isKeyboardVisible && shouldUseOnScreenKeyboard()) {
488
+ if (keyCode(event).matchesAny("Escape", "Back")) {
489
+ event.preventDefault();
490
+ event.stopPropagation();
491
+ this.handleKeyboardDismiss();
492
+
493
+ return;
494
+ }
495
+ }
496
+
454
497
  /**
455
498
  When the player is displayed, we listen to Native Play / Pause / Stop
456
499
  buttons. Any other key press will display the transport controls
@@ -567,7 +610,10 @@ export function withInteractionManager(Component: React.FC) {
567
610
  }
568
611
 
569
612
  if (keyCode(event).matches(KEYS.Exit)) {
570
- if (Platform.OS === ("samsung_tv" as QuickBrickPlatforms)) {
613
+ if (
614
+ Platform.OS === ("samsung_tv" as QuickBrickPlatforms) ||
615
+ shouldUseOnScreenKeyboard()
616
+ ) {
571
617
  this.performExit();
572
618
 
573
619
  return;
@@ -658,8 +704,73 @@ export function withInteractionManager(Component: React.FC) {
658
704
  this.confirmDialog.hideDialog();
659
705
  }
660
706
 
707
+ handleInputFocus = (event: FocusEvent) => {
708
+ if (!shouldUseOnScreenKeyboard()) return;
709
+ const target = event.target as HTMLElement;
710
+
711
+ if (this.isDismissing) {
712
+ return;
713
+ }
714
+
715
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
716
+ this.setState({
717
+ isKeyboardVisible: true,
718
+ keyboardInput: (target as HTMLInputElement).value || "",
719
+ });
720
+ }
721
+ };
722
+
723
+ handleInputBlur(event: FocusEvent) {
724
+ if (!shouldUseOnScreenKeyboard()) return;
725
+
726
+ const target = event.target as HTMLElement;
727
+
728
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
729
+ const relatedTarget = event.relatedTarget as HTMLElement;
730
+
731
+ if (
732
+ !relatedTarget ||
733
+ (relatedTarget.tagName !== "INPUT" &&
734
+ relatedTarget.tagName !== "TEXTAREA")
735
+ ) {
736
+ this.setState({ isKeyboardVisible: false });
737
+ }
738
+ }
739
+ }
740
+
741
+ handleKeyboardDismiss = () => {
742
+ this.isDismissing = true;
743
+
744
+ this.setState(
745
+ {
746
+ isKeyboardVisible: false,
747
+ keyboardInput: "",
748
+ },
749
+ () => {
750
+ setTimeout(() => {
751
+ this.isDismissing = false;
752
+ }, 100);
753
+ }
754
+ );
755
+ };
756
+
757
+ handleKeyboardInput(value: string) {
758
+ this.setState({ keyboardInput: value });
759
+ }
760
+
661
761
  render() {
662
- return <Component {...this.props} />;
762
+ return (
763
+ <>
764
+ <Component {...this.props} />
765
+ {shouldUseOnScreenKeyboard() && this.state.isKeyboardVisible && (
766
+ <OnScreenKeyboard
767
+ initialValue={this.state.keyboardInput}
768
+ onInput={this.handleKeyboardInput}
769
+ onDismiss={this.handleKeyboardDismiss}
770
+ />
771
+ )}
772
+ </>
773
+ );
663
774
  }
664
775
  }
665
776
 
@@ -8,11 +8,7 @@ export const appLoaderImpl =
8
8
  ) =>
9
9
  async (dispatch, getState) => {
10
10
  try {
11
- const {
12
- plugins,
13
- pluginConfigurations,
14
- remoteConfigurations: { localizations },
15
- } = getState();
11
+ const { plugins, pluginConfigurations } = getState();
16
12
 
17
13
  // Await crucial tasks
18
14
  await loadLocale();
@@ -20,7 +16,7 @@ export const appLoaderImpl =
20
16
  await loadAnalyticsPlugins(plugins, pluginConfigurations);
21
17
 
22
18
  // Remaining loaders
23
- const loaders = [loadDomPlugins(plugins), setUpRTL(localizations)];
19
+ const loaders = [loadDomPlugins(plugins), setUpRTL()];
24
20
 
25
21
  // Await for the remaining tasks and return when they are all complete
26
22
  await Promise.all(loaders);
@@ -1,7 +1,7 @@
1
- import { getIsRTLFromLocalizations } from "@applicaster/zapp-react-native-utils/localizationUtils";
1
+ import { getIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
2
2
  import { I18nManager } from "react-native";
3
3
 
4
- export async function setUpRTL(localizations) {
5
- const isRTL = getIsRTLFromLocalizations(localizations);
4
+ export async function setUpRTL() {
5
+ const isRTL = getIsRTL();
6
6
  I18nManager.forceRTL(isRTL);
7
7
  }
@@ -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
  /**
@@ -1,7 +1,6 @@
1
1
  import * as R from "ramda";
2
2
  import { appStore as AppStore } from "@applicaster/zapp-react-native-redux/AppStore";
3
3
  import { NativeModules } from "react-native";
4
- import { getAppData } from "../../../Polyfills/AppData";
5
4
 
6
5
  export const UI_LANGUAGE = "uiLanguage";
7
6
 
@@ -15,11 +14,11 @@ export const persistLanguageSelection = async (languageCode) => {
15
14
  return NativeModules.LocalStorage.setItem(UI_LANGUAGE, languageCode);
16
15
  };
17
16
 
18
- export const getAvailableAppLanguagesImpl = () => {
17
+ export const getAvailableAppLanguagesImpl = (appStore) => {
19
18
  try {
20
- const { languages } = getAppData();
19
+ const remoteConfigurations = appStore.get("remoteConfigurations");
21
20
 
22
- return languages;
21
+ return R.keys(remoteConfigurations.localizations);
23
22
  } catch (e) {
24
23
  return [];
25
24
  }
@@ -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,21 @@ export const getDeviceData = async () => {
253
283
  ...tizenConnectionInfo,
254
284
  device_type: getDeviceType(),
255
285
  };
286
+ } else if (hasVizioAPIs()) {
287
+ window.VIZIO.getFirmwareVersion(function (firmwareVersion) {
288
+ deviceData.osVersion = firmwareVersion;
289
+ });
290
+
291
+ deviceData = {
292
+ ...deviceData,
293
+ platform: "vizio",
294
+ deviceMake: "Vizio",
295
+ deviceModel: window.VIZIO.deviceModel,
296
+ deviceType: "tv",
297
+ userAgent: getUserAgent(),
298
+ deviceWidth: window.innerWidth,
299
+ deviceHeight: window.innerHeight,
300
+ };
256
301
  }
257
302
 
258
303
  return deviceData;
@@ -8,4 +8,5 @@ export enum STORAGE {
8
8
  export enum STORE_PLATFORM {
9
9
  lg = "lg_content_store",
10
10
  samsung = "samsung_app_store",
11
+ vizio = "vizio_app_store",
11
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-dom-app",
3
- "version": "12.0.0-alpha.4802689107",
3
+ "version": "12.0.0-alpha.4840257570",
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-alpha.4802689107",
26
- "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4802689107",
27
- "@applicaster/zapp-react-native-redux": "12.0.0-alpha.4802689107",
28
- "@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.4802689107",
29
- "@applicaster/zapp-react-native-utils": "12.0.0-alpha.4802689107",
25
+ "@applicaster/zapp-react-dom-ui-components": "12.0.0-alpha.4840257570",
26
+ "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4840257570",
27
+ "@applicaster/zapp-react-native-redux": "12.0.0-alpha.4840257570",
28
+ "@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.4840257570",
29
+ "@applicaster/zapp-react-native-utils": "12.0.0-alpha.4840257570",
30
30
  "abortcontroller-polyfill": "^1.7.5",
31
31
  "history": "^4.7.2",
32
32
  "react-router-dom": "^5.1.2",
@@ -1,22 +0,0 @@
1
- jest.mock("../../../../Polyfills/AppData", () => ({
2
- getAppData: jest.fn(),
3
- }));
4
-
5
- describe("getAvailableAppLanguages", () => {
6
- const { getAppData } = require("../../../../Polyfills/AppData");
7
- const { getAvailableAppLanguagesImpl } = require("..");
8
-
9
- it("return list of languages", () => {
10
- const languages = ["en", "de", "fr", "en-UK", "en-GB"];
11
-
12
- getAppData.mockReturnValue({ languages });
13
-
14
- expect(getAvailableAppLanguagesImpl()).toEqual(languages);
15
- });
16
-
17
- it("return list of languages", () => {
18
- getAppData.mockReturnValue(undefined);
19
-
20
- expect(getAvailableAppLanguagesImpl()).toEqual([]);
21
- });
22
- });