@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.
- package/App/InteractionManager/index.tsx +119 -8
- package/App/Loader/appLoader.js +2 -6
- package/App/Loader/setUpRTL.js +3 -3
- package/App/Loader/utils/const.js +3 -0
- package/App/Loader/utils/index.js +3 -4
- package/App/Loader/utils/platform.js +45 -0
- package/Polyfills/AppLoaderBridge/utils/enums.ts +1 -0
- package/package.json +6 -6
- package/App/Loader/utils/__tests__/getAvailableAppLanguages.test.js +0 -22
|
@@ -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 (
|
|
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 (
|
|
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
|
|
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
|
|
package/App/Loader/appLoader.js
CHANGED
|
@@ -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(
|
|
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);
|
package/App/Loader/setUpRTL.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
2
2
|
import { I18nManager } from "react-native";
|
|
3
3
|
|
|
4
|
-
export async function setUpRTL(
|
|
5
|
-
const isRTL =
|
|
4
|
+
export async function setUpRTL() {
|
|
5
|
+
const isRTL = getIsRTL();
|
|
6
6
|
I18nManager.forceRTL(isRTL);
|
|
7
7
|
}
|
|
@@ -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
|
|
19
|
+
const remoteConfigurations = appStore.get("remoteConfigurations");
|
|
21
20
|
|
|
22
|
-
return
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-dom-app",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
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.
|
|
26
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-alpha.
|
|
27
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-alpha.
|
|
28
|
-
"@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.
|
|
29
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.
|
|
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
|
-
});
|