@applicaster/zapp-react-native-utils 13.0.0-alpha.6095951301 → 13.0.0-alpha.6234681660
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/README.md +0 -10
- package/actionsExecutor/ActionExecutor.ts +16 -9
- package/actionsExecutor/ActionExecutorContext.tsx +136 -9
- package/analyticsUtils/currentScreenProperities.ts +6 -4
- package/appUtils/HooksManager/Hook.ts +2 -2
- package/appUtils/HooksManager/index.ts +1 -1
- package/appUtils/HooksManager/types.ts +5 -2
- package/appUtils/contextKeysManager/contextResolver.ts +7 -14
- package/appUtils/contextKeysManager/index.ts +2 -2
- package/appUtils/contextKeysManager/utils/index.ts +2 -1
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +1 -0
- package/appUtils/focusManager/index.ts +11 -12
- package/appUtils/focusManagerAux/utils/index.ts +4 -3
- package/appUtils/keyCodes/index.ts +11 -7
- package/appUtils/orientationHelper.ts +11 -13
- package/appUtils/platform/const.ts +14 -0
- package/appUtils/platform/platformUtils.ts +47 -4
- package/appUtils/playerManager/index.ts +1 -1
- package/appUtils/playerManager/player.ts +26 -14
- package/appUtils/playerManager/playerNative.ts +18 -3
- package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
- package/equalUtils/index.ts +49 -30
- package/focusManager/FocusManager.ts +11 -1
- package/focusManager/index.ts +49 -4
- package/functionUtils/index.ts +21 -8
- package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
- package/idleUtils/index.ts +1 -1
- package/idleUtils/withTimeout.ts +15 -2
- package/logger/const.ts +9 -67
- package/manifestUtils/__tests__/createConfig.test.js +0 -2
- package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
- package/manifestUtils/fonts/index.js +5 -6
- package/manifestUtils/sharedConfiguration/screenPicker/__tests__/utils.test.js +304 -0
- package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +875 -0
- package/manifestUtils/sharedConfiguration/screenPicker/utils.js +130 -0
- package/navigationUtils/index.ts +3 -3
- package/numberUtils/index.ts +7 -5
- package/package.json +4 -10
- package/playerUtils/configurationGenerator.ts +8 -0
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +5 -7
- package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
- package/reactHooks/cell-click/__tests__/index.test.js +5 -0
- package/reactHooks/cell-click/index.ts +7 -1
- package/reactHooks/feed/useFeedLoader.tsx +5 -3
- package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +39 -0
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +1 -1
- package/reactHooks/layout/useDimensions/useDimensions.ts +8 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +6 -17
- package/reactHooks/navigation/index.ts +13 -23
- package/reactHooks/navigation/useGetTabBarHeight.ts +1 -3
- package/reactHooks/navigation/useProfilerLogging.ts +15 -0
- package/reactHooks/navigation/useRoute.ts +2 -4
- package/reactHooks/state/useRefWithInitialValue.ts +14 -0
- package/reactHooks/state/useStateFromSubscribe.ts +23 -0
- package/reactHooks/usePluginConfiguration.ts +1 -1
- package/reactHooks/useSubscriberFor.ts +4 -3
- package/reactUtils/__tests__/__snapshots__/reactUtilsHelpers.test.js.snap +16 -4
- package/reactUtils/__tests__/reactUtils.test.js +1 -19
- package/reactUtils/__tests__/reactUtilsHelpers.test.js +72 -71
- package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +6 -72
- package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -28
- package/reactUtils/createContext/__tests__/__snapshots__/withConsumer.test.js.snap +3 -4
- package/reactUtils/createContext/__tests__/__snapshots__/withProvider.test.js.snap +7 -3
- package/reactUtils/createContext/__tests__/helpers.test.js +107 -121
- package/reactUtils/createContext/__tests__/{index.test.js → index.test.ts} +2 -2
- package/reactUtils/createContext/__tests__/provider.test.js +4 -6
- package/reactUtils/createContext/__tests__/withConsumer.test.js +12 -12
- package/reactUtils/createContext/__tests__/withProvider.test.js +4 -4
- package/reactUtils/createContext/helpers.ts +6 -1
- package/reactUtils/createContext/index.ts +11 -25
- package/reactUtils/index.ts +0 -11
- package/screenState/index.ts +24 -10
- package/services/js2native.ts +673 -0
- package/testUtils/index.tsx +0 -10
- package/theme/index.ts +1 -1
- package/time/BackgroundTimer.ts +55 -0
- package/time/Timer.ts +9 -6
- package/types.ts +1 -0
- package/zappFrameworkUtils/loginPluginUtils.ts +6 -2
- package/zappFrameworkUtils/presentPluginOneTime.ts +2 -3
- package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
- /package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
package/README.md
CHANGED
|
@@ -376,16 +376,6 @@ useEffect(() => {
|
|
|
376
376
|
}, []);
|
|
377
377
|
```
|
|
378
378
|
|
|
379
|
-
### testUtils
|
|
380
|
-
|
|
381
|
-
`@applicaster/zapp-react-native-utils/testUtils`
|
|
382
|
-
|
|
383
|
-
- `testIDEquals: (testId: any) => boolean | { width: number, height: number }` - Function to be used in tandem with enzyme findWhere
|
|
384
|
-
|
|
385
|
-
```javascript
|
|
386
|
-
wrapper.findWhere(testIDEquals("text"));
|
|
387
|
-
```
|
|
388
|
-
|
|
389
379
|
### appUtils - contextKeysManager
|
|
390
380
|
|
|
391
381
|
`@applicaster/zapp-react-native-utils/appUtils/contextKeyManager`
|
|
@@ -17,9 +17,10 @@ class ActionExecutor {
|
|
|
17
17
|
|
|
18
18
|
handleAction = async (
|
|
19
19
|
action: ActionType,
|
|
20
|
-
|
|
20
|
+
context?: Record<string, any>
|
|
21
21
|
): Promise<ActionResult> => {
|
|
22
22
|
const handler = this.registeredActions[action.type];
|
|
23
|
+
const entry = context?.entry as ZappEntry;
|
|
23
24
|
|
|
24
25
|
if (!handler) {
|
|
25
26
|
log_error(
|
|
@@ -38,11 +39,11 @@ class ActionExecutor {
|
|
|
38
39
|
);
|
|
39
40
|
|
|
40
41
|
try {
|
|
41
|
-
return handler(action,
|
|
42
|
+
return handler(action, context);
|
|
42
43
|
} catch (error) {
|
|
43
44
|
log_error(
|
|
44
45
|
`handleAction: error handling action type: ${action.type}, message: ${error.message}`,
|
|
45
|
-
{ action,
|
|
46
|
+
{ action, context, error }
|
|
46
47
|
);
|
|
47
48
|
|
|
48
49
|
throw error;
|
|
@@ -51,11 +52,11 @@ class ActionExecutor {
|
|
|
51
52
|
|
|
52
53
|
handleActions = async (
|
|
53
54
|
actionTypes: ActionType[],
|
|
54
|
-
|
|
55
|
+
context?: Record<string, any>
|
|
55
56
|
): Promise<ActionResult> => {
|
|
56
57
|
for (const action of actionTypes) {
|
|
57
58
|
// TODO: Handle action result error
|
|
58
|
-
const result = await this.handleAction(action,
|
|
59
|
+
const result = await this.handleAction(action, context);
|
|
59
60
|
|
|
60
61
|
if (result === ActionResult.Cancel) {
|
|
61
62
|
log_info(`handleActions: action: ${action.type} canceled`);
|
|
@@ -67,7 +68,10 @@ class ActionExecutor {
|
|
|
67
68
|
return ActionResult.Success;
|
|
68
69
|
};
|
|
69
70
|
|
|
70
|
-
handleEntryActions = async (
|
|
71
|
+
handleEntryActions = async (
|
|
72
|
+
entry: ZappEntry,
|
|
73
|
+
context?: Record<string, any>
|
|
74
|
+
): Promise<ActionResult> => {
|
|
71
75
|
const tapActions = entry.extensions?.tap_actions?.actions;
|
|
72
76
|
|
|
73
77
|
if (!tapActions) {
|
|
@@ -77,7 +81,7 @@ class ActionExecutor {
|
|
|
77
81
|
if (!Array.isArray(tapActions)) {
|
|
78
82
|
log_error(
|
|
79
83
|
`handleEntryActions: tapActions is not an array for id: ${entry.id} title: ${entry.title}`,
|
|
80
|
-
{ entry }
|
|
84
|
+
{ context, entry }
|
|
81
85
|
);
|
|
82
86
|
|
|
83
87
|
return;
|
|
@@ -87,7 +91,7 @@ class ActionExecutor {
|
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
await this.handleActions(tapActions, entry);
|
|
94
|
+
await this.handleActions(tapActions, { ...context, entry });
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
unregisterAction = (actionType: string) => {
|
|
@@ -96,7 +100,10 @@ class ActionExecutor {
|
|
|
96
100
|
|
|
97
101
|
registerAction = (
|
|
98
102
|
type: string,
|
|
99
|
-
handler: (
|
|
103
|
+
handler: (
|
|
104
|
+
action: ActionType,
|
|
105
|
+
context?: Record<string, any>
|
|
106
|
+
) => Promise<ActionResult>
|
|
100
107
|
) => {
|
|
101
108
|
if (this.registeredActions[type]) {
|
|
102
109
|
log_error(`registerAction: action type: ${type} already registered`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
3
|
-
import React, { createContext, useMemo } from "react";
|
|
3
|
+
import React, { createContext, useEffect, useMemo } from "react";
|
|
4
4
|
import {
|
|
5
5
|
actionExecutor as _actionExecutor,
|
|
6
6
|
ActionResult,
|
|
@@ -13,12 +13,21 @@ import { createCloudEvent, sendCloudEvent } from "../cloudEventsUtils";
|
|
|
13
13
|
import { createLogger } from "../logger";
|
|
14
14
|
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
15
15
|
import { ACTIVE_LAYOUT_ID_STORAGE_KEY } from "@applicaster/quick-brick-core/App/remoteContextReloader/consts";
|
|
16
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
17
|
+
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
16
18
|
import {
|
|
17
19
|
EntryResolver,
|
|
18
20
|
resolveObjectValues,
|
|
19
21
|
} from "../appUtils/contextKeysManager/contextResolver";
|
|
22
|
+
import { useNavigation } from "../reactHooks";
|
|
23
|
+
import { get } from "lodash";
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
import {
|
|
26
|
+
useContentTypes,
|
|
27
|
+
usePickFromState,
|
|
28
|
+
} from "@applicaster/zapp-react-native-redux/hooks";
|
|
29
|
+
|
|
30
|
+
export const { log_error, log_info, log_debug } = createLogger({
|
|
22
31
|
subsystem: "ActionExecutorContext",
|
|
23
32
|
category: "General",
|
|
24
33
|
});
|
|
@@ -26,20 +35,45 @@ const { log_error, log_info } = createLogger({
|
|
|
26
35
|
type ActionExecutorContextType = {
|
|
27
36
|
registerAction: (
|
|
28
37
|
type: string,
|
|
29
|
-
handler: (
|
|
38
|
+
handler: (
|
|
39
|
+
action: ActionType,
|
|
40
|
+
context?: Record<string, any>
|
|
41
|
+
) => Promise<ActionResult>
|
|
30
42
|
) => void;
|
|
31
43
|
unregisterAction: (type: string) => void;
|
|
32
|
-
handleAction: (
|
|
44
|
+
handleAction: (
|
|
45
|
+
action: ActionType,
|
|
46
|
+
context?: Record<string, any>
|
|
47
|
+
) => Promise<ActionResult>;
|
|
33
48
|
handleActions: (
|
|
34
49
|
actions: ActionType[],
|
|
35
|
-
|
|
50
|
+
context: Record<string, any>
|
|
51
|
+
) => Promise<ActionResult>;
|
|
52
|
+
handleEntryActions: (
|
|
53
|
+
entry: ZappEntry,
|
|
54
|
+
context?: Record<string, any>
|
|
36
55
|
) => Promise<ActionResult>;
|
|
37
|
-
handleEntryActions: (entry: ZappEntry) => Promise<ActionResult>;
|
|
38
56
|
};
|
|
39
57
|
type Props = {
|
|
40
58
|
children: React.ReactNode;
|
|
41
59
|
};
|
|
42
60
|
|
|
61
|
+
function findParentComponent(
|
|
62
|
+
childId: string,
|
|
63
|
+
parent: ZappRiver | ZappUIComponent
|
|
64
|
+
): ZappRiver | ZappUIComponent | null {
|
|
65
|
+
for (const child of parent.ui_components) {
|
|
66
|
+
if (child.id === childId) return parent;
|
|
67
|
+
|
|
68
|
+
if (child.ui_components) {
|
|
69
|
+
const found = findParentComponent(childId, child);
|
|
70
|
+
if (found) return found;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
43
77
|
const prepareDefaultActions = (actionExecutor) => {
|
|
44
78
|
actionExecutor.registerAction("localStorageSet", async (action) => {
|
|
45
79
|
const namespaces = action.options.content;
|
|
@@ -49,6 +83,33 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
49
83
|
return ActionResult.Success;
|
|
50
84
|
});
|
|
51
85
|
|
|
86
|
+
actionExecutor.registerAction(
|
|
87
|
+
"refreshComponent",
|
|
88
|
+
async (_action, context) => {
|
|
89
|
+
const dispatch = appStore.getDispatch();
|
|
90
|
+
|
|
91
|
+
const dataSource =
|
|
92
|
+
context?.component?.data?.source ||
|
|
93
|
+
findParentComponent(context?.component.id, context?.screenData)?.data
|
|
94
|
+
?.source;
|
|
95
|
+
|
|
96
|
+
log_info(`handleAction: refreshComponent for dataSource:${dataSource}`);
|
|
97
|
+
|
|
98
|
+
// TODO: In theory we should wait callback to complete, before completing the action, but now it's not needed
|
|
99
|
+
// TODO: handle focused item removal
|
|
100
|
+
dispatch(
|
|
101
|
+
loadPipesData(dataSource, {
|
|
102
|
+
silentRefresh: false,
|
|
103
|
+
clearCache: true,
|
|
104
|
+
callback: (_data) => {},
|
|
105
|
+
riverId: context?.screenData?.id,
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return ActionResult.Success;
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
|
|
52
113
|
actionExecutor.registerAction("switchLayout", async (action) => {
|
|
53
114
|
log_info("handleAction: switchLayout event");
|
|
54
115
|
|
|
@@ -84,10 +145,11 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
84
145
|
return confirmationPromise;
|
|
85
146
|
});
|
|
86
147
|
|
|
87
|
-
actionExecutor.registerAction("sendCloudEvent", async (action,
|
|
148
|
+
actionExecutor.registerAction("sendCloudEvent", async (action, context) => {
|
|
88
149
|
try {
|
|
89
150
|
const options = action.options;
|
|
90
151
|
|
|
152
|
+
const entry = context?.entry || {};
|
|
91
153
|
const entryResolver = new EntryResolver(entry);
|
|
92
154
|
|
|
93
155
|
const data =
|
|
@@ -128,9 +190,33 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
128
190
|
|
|
129
191
|
actionExecutor.registerAction(
|
|
130
192
|
"localStorageToggleFlag",
|
|
131
|
-
async (
|
|
193
|
+
async (
|
|
194
|
+
action: ActionType,
|
|
195
|
+
context?: Record<string, any>
|
|
196
|
+
): Promise<ActionResult> => {
|
|
197
|
+
if (!context) {
|
|
198
|
+
log_error(
|
|
199
|
+
"handleAction: localStorageToggleFlag action missing context"
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
return ActionResult.Error;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const entry = context?.entry as ZappEntry;
|
|
206
|
+
|
|
207
|
+
if (!entry) {
|
|
208
|
+
log_error(
|
|
209
|
+
"handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
return ActionResult.Error;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const tag = action.options?.selector
|
|
216
|
+
? get(entry, action.options.selector)
|
|
217
|
+
: (entry.extensions?.tag ?? entry.id);
|
|
218
|
+
|
|
132
219
|
const keyNamespace = action.options?.key;
|
|
133
|
-
const tag = entry?.extensions?.tag;
|
|
134
220
|
|
|
135
221
|
if (keyNamespace && tag) {
|
|
136
222
|
const multiSelectProvider =
|
|
@@ -171,6 +257,10 @@ export function withActionExecutor(Component) {
|
|
|
171
257
|
prepareDefaultActions(_actionExecutor);
|
|
172
258
|
|
|
173
259
|
return function ActionExecutorComponent(props: Props) {
|
|
260
|
+
const navigator = useNavigation();
|
|
261
|
+
const { rivers } = usePickFromState(["rivers"]);
|
|
262
|
+
const contentTypes = useContentTypes();
|
|
263
|
+
|
|
174
264
|
const handlers = useMemo(() => {
|
|
175
265
|
return {
|
|
176
266
|
unregisterAction: _actionExecutor.unregisterAction,
|
|
@@ -181,6 +271,43 @@ export function withActionExecutor(Component) {
|
|
|
181
271
|
};
|
|
182
272
|
}, []);
|
|
183
273
|
|
|
274
|
+
useEffect(() => {
|
|
275
|
+
return _actionExecutor.registerAction(
|
|
276
|
+
"navigateToScreen",
|
|
277
|
+
async (action: ActionType, _context?: Record<string, any>) => {
|
|
278
|
+
const screenType = action.options?.typeMapping;
|
|
279
|
+
|
|
280
|
+
if (!screenType) {
|
|
281
|
+
log_error("navigateToScreen: typeMapping option is missing");
|
|
282
|
+
|
|
283
|
+
return ActionResult.Error;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const screenId = contentTypes?.[screenType]?.screen_id || null;
|
|
287
|
+
|
|
288
|
+
if (!screenId) {
|
|
289
|
+
log_error(
|
|
290
|
+
`navigateToScreen: can not resolve screen type mapping: ${screenType}`
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return ActionResult.Error;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const river = rivers[screenId];
|
|
297
|
+
|
|
298
|
+
if (!river) {
|
|
299
|
+
log_error("navigateToScreen: can not resolve river");
|
|
300
|
+
|
|
301
|
+
return ActionResult.Error;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
navigator.replace(river);
|
|
305
|
+
|
|
306
|
+
return ActionResult.Success;
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
}, [navigator, rivers, contentTypes]);
|
|
310
|
+
|
|
184
311
|
return (
|
|
185
312
|
<ActionExecutorContext.Provider value={handlers}>
|
|
186
313
|
<Component {...props} />
|
|
@@ -72,12 +72,14 @@ const mappedScreenPropertiesScreen = (
|
|
|
72
72
|
screenData
|
|
73
73
|
): AnalyticsScreenProperties => {
|
|
74
74
|
return {
|
|
75
|
-
screen_name: screenData?.targetScreen?.name,
|
|
75
|
+
screen_name: screenData?.targetScreen?.name || screenData?.name,
|
|
76
76
|
screen_entry_title: screenData?.title,
|
|
77
77
|
screen_entry_id: R.isNil(screenData?.type) ? null : screenData?.id,
|
|
78
|
-
screen_layout_id: screenData?.targetScreen?.id,
|
|
79
|
-
screen_type: screenData?.targetScreen?.type,
|
|
80
|
-
home_screen: screenData?.targetScreen?.home
|
|
78
|
+
screen_layout_id: screenData?.targetScreen?.id || screenData?.id,
|
|
79
|
+
screen_type: screenData?.targetScreen?.type || screenData?.type,
|
|
80
|
+
home_screen: !R.isNil(screenData?.targetScreen?.home)
|
|
81
|
+
? screenData?.targetScreen?.home
|
|
82
|
+
: screenData?.home,
|
|
81
83
|
};
|
|
82
84
|
};
|
|
83
85
|
|
|
@@ -16,7 +16,7 @@ const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
|
|
|
16
16
|
* @returns {number} index
|
|
17
17
|
*/
|
|
18
18
|
const hookState: (
|
|
19
|
-
arg0: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS]
|
|
19
|
+
arg0: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS]
|
|
20
20
|
) => number = R.indexOf(R.__, R.values(HOOKS_EVENTS));
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -62,7 +62,7 @@ export class Hook implements HookInterface {
|
|
|
62
62
|
* @param {Array<Any>} args variadic arguments to invoke the handler with
|
|
63
63
|
*/
|
|
64
64
|
setStateAndNotify(
|
|
65
|
-
event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
|
|
65
|
+
event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
|
|
66
66
|
...args
|
|
67
67
|
) {
|
|
68
68
|
this.state = hookState(event);
|
|
@@ -84,7 +84,7 @@ export function HooksManager({
|
|
|
84
84
|
plugins,
|
|
85
85
|
startUpHooksData = {},
|
|
86
86
|
}: HookManagerArgs): HookManager {
|
|
87
|
-
hooksManagerLogger.addContext({ targetScreen });
|
|
87
|
+
hooksManagerLogger.addContext({ targetScreenId: targetScreen.id });
|
|
88
88
|
|
|
89
89
|
function logHookEvent(func, message, data) {
|
|
90
90
|
func({
|
|
@@ -4,6 +4,8 @@ import { HOOKS_EVENTS } from "./constants";
|
|
|
4
4
|
export interface HookConfiguration {}
|
|
5
5
|
|
|
6
6
|
/* existing Hook Plugn props: sample */
|
|
7
|
+
|
|
8
|
+
/*
|
|
7
9
|
interface _HookModulePlugin {
|
|
8
10
|
Component:
|
|
9
11
|
| React.FC<HookPluginProps>
|
|
@@ -23,6 +25,7 @@ interface _HookModulePlugin {
|
|
|
23
25
|
presentUI: (payload?: HookPluginProps["payload"]) => void
|
|
24
26
|
) => any;
|
|
25
27
|
}
|
|
28
|
+
*/
|
|
26
29
|
|
|
27
30
|
//* Derived from usage */
|
|
28
31
|
export interface HookModule {
|
|
@@ -100,7 +103,7 @@ export interface Hook<T extends HookModule = HookModule> {
|
|
|
100
103
|
identifier: string;
|
|
101
104
|
configuration: T["configuration"];
|
|
102
105
|
setStateAndNotify(
|
|
103
|
-
event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
|
|
106
|
+
event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
|
|
104
107
|
opts: {
|
|
105
108
|
error?: typeof Error;
|
|
106
109
|
route?: string;
|
|
@@ -109,7 +112,7 @@ export interface Hook<T extends HookModule = HookModule> {
|
|
|
109
112
|
}
|
|
110
113
|
);
|
|
111
114
|
general?: {
|
|
112
|
-
transition_type: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS];
|
|
115
|
+
transition_type: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS];
|
|
113
116
|
allow_screen_plugin_presentation: boolean;
|
|
114
117
|
is_flow_blocker: boolean;
|
|
115
118
|
};
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { createLogger } from "../../logger";
|
|
2
1
|
import { ContextKeysManager } from "./index";
|
|
3
2
|
import * as R from "ramda";
|
|
4
3
|
|
|
5
|
-
const { log_error } = createLogger({
|
|
6
|
-
subsystem: "contextResolver",
|
|
7
|
-
category: "General",
|
|
8
|
-
});
|
|
9
|
-
|
|
10
4
|
interface IResolver {
|
|
11
5
|
resolve: (string) => Promise<string | number | object>;
|
|
12
6
|
}
|
|
@@ -42,12 +36,16 @@ export const resolveObjectValues = async (
|
|
|
42
36
|
|
|
43
37
|
const resolvedEntries = await Promise.all(
|
|
44
38
|
entries.map(async ([key, value]) => {
|
|
45
|
-
const regex = /@{([^/]+)\/([^}]*)}/;
|
|
46
|
-
|
|
47
39
|
if (typeof value !== "string") {
|
|
48
40
|
return [key, value];
|
|
49
41
|
}
|
|
50
42
|
|
|
43
|
+
if (!value.startsWith("@")) {
|
|
44
|
+
return [key, value];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const regex = /@{([^/]+)\/([^}]*)}/;
|
|
48
|
+
|
|
51
49
|
const match = (value as string).match(regex);
|
|
52
50
|
|
|
53
51
|
if (match) {
|
|
@@ -60,12 +58,7 @@ export const resolveObjectValues = async (
|
|
|
60
58
|
return [key, resolvedValue];
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
key,
|
|
65
|
-
value,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
return [key, null];
|
|
61
|
+
return [key, value];
|
|
69
62
|
})
|
|
70
63
|
);
|
|
71
64
|
|
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
|
|
17
17
|
export { StorageLevel };
|
|
18
18
|
|
|
19
|
-
type KeyNameObj = {
|
|
19
|
+
export type KeyNameObj = {
|
|
20
20
|
namespace: string;
|
|
21
21
|
key: string;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
type KeyName = string | KeyNameObj;
|
|
24
|
+
export type KeyName = string | KeyNameObj;
|
|
25
25
|
|
|
26
26
|
type ParsedKeyAndNamespace = {
|
|
27
27
|
namespace?: string;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import { DEFAULT_NAMESPACE } from "../consts";
|
|
3
|
+
import { KeyName, KeyNameObj } from "../index";
|
|
3
4
|
|
|
4
5
|
const lastDotRegex = /\.([^.]+)$/;
|
|
5
6
|
const splitByLastDot = R.compose(R.init, R.split(lastDotRegex));
|
|
6
7
|
|
|
7
|
-
export function getNamespaceAndKey(namespacedKey) {
|
|
8
|
+
export function getNamespaceAndKey(namespacedKey: KeyName): KeyNameObj {
|
|
8
9
|
if (typeof namespacedKey !== "string") return namespacedKey;
|
|
9
10
|
|
|
10
11
|
const namespacedKeyProps = namespacedKey.includes(".")
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { subscriber } from "../../functionUtils";
|
|
14
14
|
import { coreLogger } from "../../logger";
|
|
15
15
|
import { ACTION } from "./utils/enums";
|
|
16
|
+
|
|
16
17
|
const logger = coreLogger.addSubsystem("focusManager");
|
|
17
18
|
|
|
18
19
|
const isFocusEnabled = (focusableItem): boolean => {
|
|
@@ -325,8 +326,6 @@ export const focusManager = (function () {
|
|
|
325
326
|
},
|
|
326
327
|
});
|
|
327
328
|
|
|
328
|
-
currentFocusNode = focusCandidate;
|
|
329
|
-
|
|
330
329
|
focusableItem && setFocus(focusCandidate.id, null);
|
|
331
330
|
|
|
332
331
|
return { success: true };
|
|
@@ -335,15 +334,14 @@ export const focusManager = (function () {
|
|
|
335
334
|
return { success: false };
|
|
336
335
|
}
|
|
337
336
|
|
|
338
|
-
function treeLoaded(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
});
|
|
337
|
+
function treeLoaded(_val, _node) {}
|
|
338
|
+
|
|
339
|
+
function pressIn() {
|
|
340
|
+
const currentFocusable = getCurrentFocus();
|
|
341
|
+
|
|
342
|
+
if (currentFocusable) {
|
|
343
|
+
currentFocusable.pressIn(null);
|
|
344
|
+
}
|
|
347
345
|
}
|
|
348
346
|
|
|
349
347
|
/**
|
|
@@ -477,7 +475,7 @@ export const focusManager = (function () {
|
|
|
477
475
|
function isCurrentFocusOnTheTopScreen() {
|
|
478
476
|
const routes = R.pathOr([], ["root", "children"], focusableTree);
|
|
479
477
|
|
|
480
|
-
if (routes.length <= 1) {
|
|
478
|
+
if (currentFocusNode && routes.length <= 1) {
|
|
481
479
|
// there is only one or zero routes
|
|
482
480
|
return true;
|
|
483
481
|
}
|
|
@@ -553,6 +551,7 @@ export const focusManager = (function () {
|
|
|
553
551
|
invokeHandler,
|
|
554
552
|
removeHandler,
|
|
555
553
|
longPress,
|
|
554
|
+
pressIn,
|
|
556
555
|
pressOut,
|
|
557
556
|
enableFocus,
|
|
558
557
|
setInitialFocus,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
2
|
-
import { find, last,
|
|
2
|
+
import { find, last, pathOr, startsWith } from "ramda";
|
|
3
3
|
import {
|
|
4
|
-
QUICK_BRICK_NAVBAR,
|
|
5
4
|
QUICK_BRICK_CONTENT,
|
|
5
|
+
QUICK_BRICK_NAVBAR,
|
|
6
6
|
} from "@applicaster/quick-brick-core/const";
|
|
7
7
|
|
|
8
8
|
// run check each 300 ms
|
|
@@ -66,7 +66,8 @@ export const getContentNode = (focusableTree) => {
|
|
|
66
66
|
const content = find(
|
|
67
67
|
(child) =>
|
|
68
68
|
startsWith(QUICK_BRICK_CONTENT, child.id) ||
|
|
69
|
-
startsWith("player", child.id)
|
|
69
|
+
startsWith("player", child.id) ||
|
|
70
|
+
startsWith("/hooks", child?.parent?.id), // For startup hooks case
|
|
70
71
|
getActiveScreenChildren(focusableTree)
|
|
71
72
|
);
|
|
72
73
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as R from "ramda";
|
|
2
|
-
|
|
3
1
|
// more keys can be added here. Simply make sure
|
|
4
2
|
// the key matches the code value
|
|
5
3
|
|
|
@@ -34,12 +32,18 @@ export function keyCode(key) {
|
|
|
34
32
|
keyCode(keyEvent).matchesAny("Enter", "Backspace", KEYS.ArrowLeft, ...)
|
|
35
33
|
*/
|
|
36
34
|
|
|
37
|
-
const matches =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const matches = (compareKey) => {
|
|
36
|
+
// If compareKey is a string, look it up in KEYS object
|
|
37
|
+
const keyToCompare =
|
|
38
|
+
typeof compareKey === "string" ? KEYS[compareKey] : compareKey;
|
|
39
|
+
|
|
40
|
+
// Compare either code or keyCode properties
|
|
41
|
+
return (
|
|
42
|
+
keyToCompare?.code === key.code || keyToCompare?.keyCode === key.keyCode
|
|
43
|
+
);
|
|
44
|
+
};
|
|
41
45
|
|
|
42
|
-
const matchesAny = (...args) =>
|
|
46
|
+
const matchesAny = (...args) => args.some(matches);
|
|
43
47
|
|
|
44
48
|
const direction = () =>
|
|
45
49
|
matchesAny(...ARROW_KEYS) ? directionHelper(key) : null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/// <reference types="@types/react-native" />
|
|
2
1
|
import * as ReactNative from "react-native";
|
|
3
|
-
import { isTV, platformSelect } from "../reactUtils";
|
|
4
2
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
import { isTV, platformSelect } from "../reactUtils";
|
|
5
|
+
import { useIsTablet } from "../reactHooks";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
QUICK_BRICK_EVENTS,
|
|
@@ -121,8 +121,15 @@ export const removeOrientationChangeListener = (listener: any): void => {
|
|
|
121
121
|
*/
|
|
122
122
|
export const isOrientationCompatible = ({
|
|
123
123
|
orientation,
|
|
124
|
-
layoutData: { width, height },
|
|
124
|
+
layoutData: { width, height, isTablet, isTabletPortrait },
|
|
125
125
|
}) => {
|
|
126
|
+
// We count portrait as compatible, because if default in zapp for mobile layout
|
|
127
|
+
// We count landscape as compatible, because if isTabletPortrait is false,
|
|
128
|
+
// it defaults for device
|
|
129
|
+
if (isTablet && !isTabletPortrait) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
126
133
|
const isLandscape = width > height;
|
|
127
134
|
|
|
128
135
|
if (
|
|
@@ -146,15 +153,6 @@ export const isOrientationCompatible = ({
|
|
|
146
153
|
return true;
|
|
147
154
|
};
|
|
148
155
|
|
|
149
|
-
export const useIsOrientationCompatible = (orientation) => {
|
|
150
|
-
const { height, width } = ReactNative.useWindowDimensions();
|
|
151
|
-
|
|
152
|
-
return isOrientationCompatible({
|
|
153
|
-
orientation,
|
|
154
|
-
layoutData: { width, height },
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
|
|
158
156
|
/**
|
|
159
157
|
* Determine final screen orientation based on device type,
|
|
160
158
|
* settings and orientation value provided by screen data settings
|
|
@@ -23,3 +23,17 @@ export const PLATFORMS = {
|
|
|
23
23
|
export const PLATFORM_KEYS = {
|
|
24
24
|
deviceClosedCaptioningEnabled: "device_closed_captioning_enabled",
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
export enum ZappPlatform {
|
|
28
|
+
Android = "android",
|
|
29
|
+
AndroidTV = "android_tv",
|
|
30
|
+
AmazonFireTV = "amazon",
|
|
31
|
+
iOS = "ios",
|
|
32
|
+
tvOS = "tvos",
|
|
33
|
+
Roku = "roku",
|
|
34
|
+
Tizen = "tizen",
|
|
35
|
+
Web = "web",
|
|
36
|
+
WebOS = "webos",
|
|
37
|
+
Vizio = "vizio",
|
|
38
|
+
Unknown = "unknown",
|
|
39
|
+
}
|