@applicaster/zapp-react-native-utils 13.0.0-alpha.5371423120 → 13.0.0-alpha.5375459737
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 +207 -11
- package/actionsExecutor/consts.ts +4 -0
- package/alertUtils/alert.ts +148 -0
- package/alertUtils/index.ts +1 -148
- package/analyticsUtils/AnalyticPlayerListener.ts +18 -1
- package/analyticsUtils/__tests__/__snapshots__/analyticsManagerNoModule.test.js.snap +9 -9
- package/analyticsUtils/currentScreenProperities.ts +6 -4
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/appUtils/HooksManager/{Hook.js → Hook.ts} +39 -23
- package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +10 -8
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
- package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
- package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
- package/appUtils/HooksManager/{index.js → index.ts} +124 -113
- package/appUtils/HooksManager/types.ts +119 -0
- package/appUtils/RiverFocusManager/index.js +17 -12
- package/appUtils/accessibilityManager/index.ts +42 -1
- package/appUtils/contextKeysManager/contextResolver.ts +66 -0
- package/appUtils/contextKeysManager/index.ts +2 -2
- package/appUtils/contextKeysManager/utils/index.ts +2 -1
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +8 -6
- package/appUtils/focusManager/index.ts +108 -69
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +25 -3
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
- package/appUtils/focusManager/utils/enums.ts +4 -0
- package/appUtils/focusManagerAux/utils/index.ts +4 -3
- package/appUtils/{index.js → index.ts} +1 -1
- package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +2 -2
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +4 -4
- package/appUtils/keyCodes/{index.js → index.ts} +13 -7
- package/appUtils/keyCodes/keys/index.ts +3 -0
- package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
- package/appUtils/keyCodes/keys/keys.android.ts +18 -0
- package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
- package/appUtils/keyCodes/keys/keys.ts +15 -0
- package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +4 -0
- package/appUtils/keyCodes/keysByPlatform.ts +8 -0
- package/appUtils/keyInputHandler/KeyInputHandler.ts +68 -0
- package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +23 -0
- package/appUtils/orientationHelper.ts +11 -13
- package/appUtils/platform/const.ts +14 -0
- package/appUtils/platform/platformUtils.ts +47 -18
- package/appUtils/playerManager/index.ts +7 -3
- package/appUtils/playerManager/player.ts +42 -18
- package/appUtils/playerManager/playerFactory.ts +5 -4
- package/appUtils/playerManager/playerNative.ts +18 -2
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -3
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +7 -1
- package/arrayUtils/__tests__/__snapshots__/arrayUtils.test.ts.snap +4 -4
- package/componentsUtils/__tests__/isFirstComponentGallery.test.ts +33 -0
- package/componentsUtils/__tests__/isFirstComponentScreenPicker.test.ts +33 -0
- package/componentsUtils/__tests__/isGallery.test.ts +33 -0
- package/componentsUtils/__tests__/isScreenPicker.test.ts +33 -0
- package/componentsUtils/index.ts +32 -0
- package/dateUtils/index.ts +19 -0
- package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
- package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
- package/equalUtils/index.ts +49 -30
- package/focusManager/FocusManager.ts +14 -2
- package/focusManager/index.ts +23 -4
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +4 -4
- package/functionUtils/index.ts +61 -19
- package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
- package/idleUtils/index.ts +1 -1
- package/idleUtils/withTimeout.ts +15 -2
- package/index.d.ts +0 -12
- package/localizationUtils/index.ts +5 -10
- package/logger/const.ts +9 -67
- package/manifestUtils/__tests__/createConfig.test.js +16 -16
- package/manifestUtils/defaultManifestConfigurations/player.js +14 -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/modalState/__tests__/index.test.ts +51 -0
- package/modalState/index.ts +33 -7
- package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +7 -6
- package/navigationUtils/__tests__/itemTypes.test.js +2 -2
- package/navigationUtils/__tests__/navigationUtils.test.js +2 -2
- package/navigationUtils/index.ts +20 -9
- package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +23 -3
- package/numberUtils/index.ts +11 -5
- package/package.json +5 -10
- package/playerUtils/configurationGenerator.ts +14 -0
- package/reactHooks/advertising/index.ts +5 -5
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +6 -8
- package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
- package/reactHooks/cell-click/__tests__/index.test.js +10 -2
- package/reactHooks/cell-click/index.ts +7 -1
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +4 -4
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +20 -13
- package/reactHooks/feed/useFeedLoader.tsx +28 -15
- package/reactHooks/feed/usePipesCacheReset.ts +5 -5
- package/reactHooks/flatList/__tests__/index.test.tsx +30 -21
- package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +39 -0
- package/reactHooks/layout/__tests__/index.test.tsx +10 -10
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +14 -28
- 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 -21
- package/reactHooks/navigation/index.ts +41 -240
- package/reactHooks/navigation/useGetBottomTabBarHeight.ts +12 -0
- package/reactHooks/navigation/useGetNavBarTopBorderWidth.ts +14 -0
- package/reactHooks/navigation/useGetTabBarHeight.ts +10 -0
- package/reactHooks/navigation/useIsScreenActive.ts +17 -0
- package/reactHooks/navigation/useNavigationPluginData.ts +15 -0
- package/reactHooks/navigation/useNavigationType.ts +15 -0
- package/reactHooks/navigation/usePathname.ts +4 -0
- package/reactHooks/navigation/useProfilerLogging.ts +15 -0
- package/reactHooks/navigation/useRoute.ts +98 -0
- package/reactHooks/navigation/useUniqueRouteSuffix.ts +41 -0
- package/reactHooks/player/TVSeekControlller/ISeekController.ts +32 -0
- package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +71 -0
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +258 -0
- package/reactHooks/player/TVSeekControlller/TapSeekController.ts +53 -0
- package/reactHooks/player/__tests__/{useAutoSeek.test.tsx → useAutoSeek._test.tsx} +2 -3
- package/reactHooks/player/const.ts +0 -4
- package/reactHooks/player/index.ts +0 -6
- 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/reactHooks/utils/index.ts +13 -0
- package/reactUtils/__tests__/__snapshots__/reactUtilsHelpers.test.js.snap +16 -4
- package/reactUtils/__tests__/reactUtils.test.js +1 -37
- package/reactUtils/__tests__/reactUtilsHelpers.test.js +72 -71
- package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +13 -79
- package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +2 -2
- 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 -25
- package/screenState/index.ts +24 -10
- package/services/js2native.ts +673 -0
- package/testUtils/index.tsx +0 -10
- package/theme/__mocks__/index.ts +4 -0
- package/theme/index.ts +1 -1
- package/time/BackgroundTimer.ts +55 -0
- package/time/Timer.ts +9 -6
- package/types.ts +1 -0
- package/utils/README.md +30 -0
- package/utils/chunk.ts +5 -0
- package/utils/index.ts +5 -0
- package/utils/times.ts +5 -0
- package/zappFrameworkUtils/localStorageHelper.ts +6 -0
- package/zappFrameworkUtils/loginPluginUtils.ts +6 -2
- package/zappFrameworkUtils/presentPluginOneTime.ts +2 -3
- package/zappFrameworkUtils/types.ts +11 -0
- package/appUtils/keyCodes/keys.ios.js +0 -46
- package/reactHooks/player/useAutoSeek.tsx +0 -87
- package/reactHooks/player/useSeek.tsx +0 -66
- package/reactHooks/player/useTapSeek.tsx +0 -58
- package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
- /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
- /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
- /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
- /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
- /package/domUtils/{logger.js → logger.ts} +0 -0
- /package/reactHooks/player/__tests__/{useTapSeek.test.ts → useTapSeek._test.ts} +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,7 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
|
-
|
|
3
|
-
import React, { createContext, useMemo } from "react";
|
|
2
|
+
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
3
|
+
import React, { createContext, useEffect, useMemo } from "react";
|
|
4
|
+
import { NativeModules } from "react-native";
|
|
4
5
|
import {
|
|
5
6
|
actionExecutor as _actionExecutor,
|
|
6
7
|
ActionResult,
|
|
@@ -12,8 +13,27 @@ import { showConfirmationDialog } from "../alertUtils";
|
|
|
12
13
|
import { createCloudEvent, sendCloudEvent } from "../cloudEventsUtils";
|
|
13
14
|
import { createLogger } from "../logger";
|
|
14
15
|
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
16
|
+
import { ACTIVE_LAYOUT_ID_STORAGE_KEY } from "@applicaster/quick-brick-core/App/remoteContextReloader/consts";
|
|
17
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
18
|
+
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
19
|
+
import {
|
|
20
|
+
EntryResolver,
|
|
21
|
+
resolveObjectValues,
|
|
22
|
+
} from "../appUtils/contextKeysManager/contextResolver";
|
|
23
|
+
import { useNavigation } from "../reactHooks";
|
|
24
|
+
import { get } from "lodash";
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
useContentTypes,
|
|
28
|
+
usePickFromState,
|
|
29
|
+
} from "@applicaster/zapp-react-native-redux/hooks";
|
|
30
|
+
import {
|
|
31
|
+
ACTION_EXECUTOR_EVENT_SOURCE,
|
|
32
|
+
TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT,
|
|
33
|
+
} from "./consts";
|
|
34
|
+
const { ReactNativeEventBusBridge } = NativeModules;
|
|
15
35
|
|
|
16
|
-
const { log_error, log_info } = createLogger({
|
|
36
|
+
export const { log_error, log_info, log_debug } = createLogger({
|
|
17
37
|
subsystem: "ActionExecutorContext",
|
|
18
38
|
category: "General",
|
|
19
39
|
});
|
|
@@ -21,20 +41,65 @@ const { log_error, log_info } = createLogger({
|
|
|
21
41
|
type ActionExecutorContextType = {
|
|
22
42
|
registerAction: (
|
|
23
43
|
type: string,
|
|
24
|
-
handler: (
|
|
44
|
+
handler: (
|
|
45
|
+
action: ActionType,
|
|
46
|
+
context?: Record<string, any>
|
|
47
|
+
) => Promise<ActionResult>
|
|
25
48
|
) => void;
|
|
26
49
|
unregisterAction: (type: string) => void;
|
|
27
|
-
handleAction: (
|
|
50
|
+
handleAction: (
|
|
51
|
+
action: ActionType,
|
|
52
|
+
context?: Record<string, any>
|
|
53
|
+
) => Promise<ActionResult>;
|
|
28
54
|
handleActions: (
|
|
29
55
|
actions: ActionType[],
|
|
30
|
-
|
|
56
|
+
context: Record<string, any>
|
|
57
|
+
) => Promise<ActionResult>;
|
|
58
|
+
handleEntryActions: (
|
|
59
|
+
entry: ZappEntry,
|
|
60
|
+
context?: Record<string, any>
|
|
31
61
|
) => Promise<ActionResult>;
|
|
32
|
-
handleEntryActions: (entry: ZappEntry) => Promise<ActionResult>;
|
|
33
62
|
};
|
|
34
63
|
type Props = {
|
|
35
64
|
children: React.ReactNode;
|
|
36
65
|
};
|
|
37
66
|
|
|
67
|
+
function findParentComponent(
|
|
68
|
+
childId: string,
|
|
69
|
+
parent: ZappRiver | ZappUIComponent
|
|
70
|
+
): ZappRiver | ZappUIComponent | null {
|
|
71
|
+
for (const child of parent.ui_components) {
|
|
72
|
+
if (child.id === childId) return parent;
|
|
73
|
+
|
|
74
|
+
if (child.ui_components) {
|
|
75
|
+
const found = findParentComponent(childId, child);
|
|
76
|
+
if (found) return found;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// send all data just in case (like for message string formatting)
|
|
84
|
+
// Type is not exported for now
|
|
85
|
+
type MaxTagsReachedEvent = {
|
|
86
|
+
// todo: current stable Android SDK crashes when we pass array from RN back to RN
|
|
87
|
+
selectedItems?: string[];
|
|
88
|
+
maxItems: number;
|
|
89
|
+
tag: string;
|
|
90
|
+
keyNamespace: string;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
async function onMaxTagsReached(data: MaxTagsReachedEvent) {
|
|
94
|
+
const event = {
|
|
95
|
+
type: TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT,
|
|
96
|
+
source: ACTION_EXECUTOR_EVENT_SOURCE,
|
|
97
|
+
data,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
await ReactNativeEventBusBridge?.postEvent(event);
|
|
101
|
+
}
|
|
102
|
+
|
|
38
103
|
const prepareDefaultActions = (actionExecutor) => {
|
|
39
104
|
actionExecutor.registerAction("localStorageSet", async (action) => {
|
|
40
105
|
const namespaces = action.options.content;
|
|
@@ -44,6 +109,46 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
44
109
|
return ActionResult.Success;
|
|
45
110
|
});
|
|
46
111
|
|
|
112
|
+
actionExecutor.registerAction(
|
|
113
|
+
"refreshComponent",
|
|
114
|
+
async (_action, context) => {
|
|
115
|
+
const dispatch = appStore.getDispatch();
|
|
116
|
+
|
|
117
|
+
const dataSource =
|
|
118
|
+
context?.component?.data?.source ||
|
|
119
|
+
findParentComponent(context?.component.id, context?.screenData)?.data
|
|
120
|
+
?.source;
|
|
121
|
+
|
|
122
|
+
log_info(`handleAction: refreshComponent for dataSource:${dataSource}`);
|
|
123
|
+
|
|
124
|
+
// TODO: In theory we should wait callback to complete, before completing the action, but now it's not needed
|
|
125
|
+
// TODO: handle focused item removal
|
|
126
|
+
dispatch(
|
|
127
|
+
loadPipesData(dataSource, {
|
|
128
|
+
silentRefresh: false,
|
|
129
|
+
clearCache: true,
|
|
130
|
+
callback: (_data) => {},
|
|
131
|
+
riverId: context?.screenData?.id,
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
return ActionResult.Success;
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
actionExecutor.registerAction("switchLayout", async (action) => {
|
|
140
|
+
log_info("handleAction: switchLayout event");
|
|
141
|
+
|
|
142
|
+
await localStorage.setItem(
|
|
143
|
+
ACTIVE_LAYOUT_ID_STORAGE_KEY,
|
|
144
|
+
action.options.layoutId
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
QuickBrickManager.sendQuickBrickEvent(QUICK_BRICK_EVENTS.FORCE_APP_RELOAD);
|
|
148
|
+
|
|
149
|
+
return ActionResult.Success;
|
|
150
|
+
});
|
|
151
|
+
|
|
47
152
|
actionExecutor.registerAction("appRestart", async () => {
|
|
48
153
|
log_info(`handleAction: ${QUICK_BRICK_EVENTS.FORCE_APP_RELOAD} event`);
|
|
49
154
|
|
|
@@ -66,13 +171,21 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
66
171
|
return confirmationPromise;
|
|
67
172
|
});
|
|
68
173
|
|
|
69
|
-
actionExecutor.registerAction("sendCloudEvent", async (action,
|
|
174
|
+
actionExecutor.registerAction("sendCloudEvent", async (action, context) => {
|
|
70
175
|
try {
|
|
71
176
|
const options = action.options;
|
|
72
177
|
|
|
178
|
+
const entry = context?.entry || {};
|
|
179
|
+
const entryResolver = new EntryResolver(entry);
|
|
180
|
+
|
|
181
|
+
const data =
|
|
182
|
+
options?.data && options.inflateData
|
|
183
|
+
? await resolveObjectValues(options.data, { entry: entryResolver })
|
|
184
|
+
: options?.data || entry;
|
|
185
|
+
|
|
73
186
|
const cloudEvent = await createCloudEvent({
|
|
74
187
|
type: options.type || "com.applicaster.selector.action.v1",
|
|
75
|
-
data
|
|
188
|
+
data,
|
|
76
189
|
subject: options.subject || entry?.id,
|
|
77
190
|
});
|
|
78
191
|
|
|
@@ -103,9 +216,33 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
103
216
|
|
|
104
217
|
actionExecutor.registerAction(
|
|
105
218
|
"localStorageToggleFlag",
|
|
106
|
-
async (
|
|
219
|
+
async (
|
|
220
|
+
action: ActionType,
|
|
221
|
+
context?: Record<string, any>
|
|
222
|
+
): Promise<ActionResult> => {
|
|
223
|
+
if (!context) {
|
|
224
|
+
log_error(
|
|
225
|
+
"handleAction: localStorageToggleFlag action missing context"
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
return ActionResult.Error;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const entry = context?.entry as ZappEntry;
|
|
232
|
+
|
|
233
|
+
if (!entry) {
|
|
234
|
+
log_error(
|
|
235
|
+
"handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
return ActionResult.Error;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const tag = action.options?.selector
|
|
242
|
+
? get(entry, action.options.selector)
|
|
243
|
+
: (entry.extensions?.tag ?? entry.id);
|
|
244
|
+
|
|
107
245
|
const keyNamespace = action.options?.key;
|
|
108
|
-
const tag = entry?.extensions?.tag;
|
|
109
246
|
|
|
110
247
|
if (keyNamespace && tag) {
|
|
111
248
|
const multiSelectProvider =
|
|
@@ -123,6 +260,23 @@ const prepareDefaultActions = (actionExecutor) => {
|
|
|
123
260
|
if (selectedItems.includes(tag)) {
|
|
124
261
|
await multiSelectProvider.removeItem(tag);
|
|
125
262
|
} else {
|
|
263
|
+
const maxItems = action.options?.max_items;
|
|
264
|
+
|
|
265
|
+
if (maxItems && selectedItems.length >= maxItems) {
|
|
266
|
+
log_info(
|
|
267
|
+
`handleAction: localStorageToggleFlag event reached max items limit: ${maxItems}, cannot add tag: ${tag}`
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
await onMaxTagsReached({
|
|
271
|
+
selectedItems,
|
|
272
|
+
maxItems,
|
|
273
|
+
tag,
|
|
274
|
+
keyNamespace,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
return ActionResult.Cancel;
|
|
278
|
+
}
|
|
279
|
+
|
|
126
280
|
await multiSelectProvider.addItem(tag);
|
|
127
281
|
}
|
|
128
282
|
} else {
|
|
@@ -146,6 +300,10 @@ export function withActionExecutor(Component) {
|
|
|
146
300
|
prepareDefaultActions(_actionExecutor);
|
|
147
301
|
|
|
148
302
|
return function ActionExecutorComponent(props: Props) {
|
|
303
|
+
const navigator = useNavigation();
|
|
304
|
+
const { rivers } = usePickFromState(["rivers"]);
|
|
305
|
+
const contentTypes = useContentTypes();
|
|
306
|
+
|
|
149
307
|
const handlers = useMemo(() => {
|
|
150
308
|
return {
|
|
151
309
|
unregisterAction: _actionExecutor.unregisterAction,
|
|
@@ -156,6 +314,44 @@ export function withActionExecutor(Component) {
|
|
|
156
314
|
};
|
|
157
315
|
}, []);
|
|
158
316
|
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
return _actionExecutor.registerAction(
|
|
319
|
+
"navigateToScreen",
|
|
320
|
+
async (action: ActionType, context?: Record<string, any>) => {
|
|
321
|
+
const screenType = action.options?.typeMapping;
|
|
322
|
+
|
|
323
|
+
if (!screenType) {
|
|
324
|
+
log_error("navigateToScreen: typeMapping option is missing");
|
|
325
|
+
|
|
326
|
+
return ActionResult.Error;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const screenId = contentTypes?.[screenType]?.screen_id || null;
|
|
330
|
+
|
|
331
|
+
if (!screenId) {
|
|
332
|
+
log_error(
|
|
333
|
+
`navigateToScreen: can not resolve screen type mapping: ${screenType}`
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
return ActionResult.Error;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const river = rivers[screenId];
|
|
340
|
+
|
|
341
|
+
if (!river) {
|
|
342
|
+
log_error("navigateToScreen: can not resolve river");
|
|
343
|
+
|
|
344
|
+
return ActionResult.Error;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
context?.callback?.({ success: false, error: null, abort: true });
|
|
348
|
+
navigator.replace(river);
|
|
349
|
+
|
|
350
|
+
return ActionResult.Success;
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
}, [navigator, rivers, contentTypes]);
|
|
354
|
+
|
|
159
355
|
return (
|
|
160
356
|
<ActionExecutorContext.Provider value={handlers}>
|
|
161
357
|
<Component {...props} />
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Alert } from "react-native";
|
|
2
|
+
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
+
import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
|
|
4
|
+
|
|
5
|
+
// #region "Alert Dialog"
|
|
6
|
+
|
|
7
|
+
const globalAny: any = global;
|
|
8
|
+
|
|
9
|
+
const showWebAlertDialog = ({ message, completion }: AlertWebDialog) => {
|
|
10
|
+
globalAny?.alert?.(message);
|
|
11
|
+
completion?.();
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const showNativeAlertDialog = ({
|
|
15
|
+
title,
|
|
16
|
+
message,
|
|
17
|
+
okButtonText,
|
|
18
|
+
completion,
|
|
19
|
+
}: AlertDialogType) => {
|
|
20
|
+
Alert.alert(title, message, [
|
|
21
|
+
{
|
|
22
|
+
text: okButtonText,
|
|
23
|
+
onPress: completion,
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const showAlertDialog = ({
|
|
29
|
+
title,
|
|
30
|
+
message,
|
|
31
|
+
okButtonText,
|
|
32
|
+
completion,
|
|
33
|
+
}: AlertDialogType) => {
|
|
34
|
+
if (isWeb()) {
|
|
35
|
+
showWebAlertDialog({ message, completion });
|
|
36
|
+
} else {
|
|
37
|
+
showNativeAlertDialog({
|
|
38
|
+
title,
|
|
39
|
+
message,
|
|
40
|
+
okButtonText,
|
|
41
|
+
completion,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// #endregion "Alert Dialog"
|
|
47
|
+
|
|
48
|
+
// #region "Confirmation Dialog"
|
|
49
|
+
|
|
50
|
+
const showWebDialog = ({
|
|
51
|
+
message,
|
|
52
|
+
confirmCompletion,
|
|
53
|
+
cancelCompletion,
|
|
54
|
+
}: WebConfirmationDialog) => {
|
|
55
|
+
const isConfirmed = globalAny?.confirm?.(message);
|
|
56
|
+
|
|
57
|
+
if (isConfirmed) {
|
|
58
|
+
confirmCompletion?.();
|
|
59
|
+
} else {
|
|
60
|
+
cancelCompletion?.();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const showNativeDialog = ({
|
|
65
|
+
title,
|
|
66
|
+
message,
|
|
67
|
+
okButtonText,
|
|
68
|
+
cancelButtonText,
|
|
69
|
+
confirmCompletion,
|
|
70
|
+
cancelCompletion,
|
|
71
|
+
}: ConfirmationDialog) => {
|
|
72
|
+
Alert.alert(title, message, [
|
|
73
|
+
{
|
|
74
|
+
text: cancelButtonText,
|
|
75
|
+
onPress: cancelCompletion,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
text: okButtonText,
|
|
79
|
+
style: "destructive",
|
|
80
|
+
onPress: confirmCompletion,
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const handleCustomDialog = (data) => {
|
|
86
|
+
const {
|
|
87
|
+
showDialog,
|
|
88
|
+
hideDialog,
|
|
89
|
+
setConfirmAction,
|
|
90
|
+
setCancelAction,
|
|
91
|
+
setMessages,
|
|
92
|
+
} = confirmationDialogStore.getState();
|
|
93
|
+
|
|
94
|
+
setMessages(data.messages);
|
|
95
|
+
|
|
96
|
+
if (data?.cancelCompletion) {
|
|
97
|
+
setCancelAction(() => {
|
|
98
|
+
data.cancelCompletion();
|
|
99
|
+
hideDialog();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (data?.confirmCompletion) {
|
|
104
|
+
setConfirmAction(() => {
|
|
105
|
+
data.confirmCompletion();
|
|
106
|
+
hideDialog();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
showDialog();
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const showConfirmationDialog = ({
|
|
114
|
+
title,
|
|
115
|
+
message,
|
|
116
|
+
okButtonText,
|
|
117
|
+
cancelButtonText,
|
|
118
|
+
confirmCompletion,
|
|
119
|
+
cancelCompletion,
|
|
120
|
+
}: CustomConfirmationDialog): void => {
|
|
121
|
+
if (isWeb()) {
|
|
122
|
+
if (cancelCompletion) {
|
|
123
|
+
handleCustomDialog({
|
|
124
|
+
messages: {
|
|
125
|
+
title,
|
|
126
|
+
message,
|
|
127
|
+
okButtonText,
|
|
128
|
+
cancelButtonText,
|
|
129
|
+
},
|
|
130
|
+
confirmCompletion,
|
|
131
|
+
cancelCompletion,
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
showWebDialog({ message, confirmCompletion, cancelCompletion });
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
showNativeDialog({
|
|
138
|
+
title,
|
|
139
|
+
message,
|
|
140
|
+
okButtonText,
|
|
141
|
+
cancelButtonText,
|
|
142
|
+
confirmCompletion,
|
|
143
|
+
cancelCompletion,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// #endregion "Confirmation Dialog"
|
package/alertUtils/index.ts
CHANGED
|
@@ -1,148 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
-
import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
|
|
4
|
-
|
|
5
|
-
// #region "Alert Dialog"
|
|
6
|
-
|
|
7
|
-
const globalAny: any = global;
|
|
8
|
-
|
|
9
|
-
const showWebAlertDialog = ({ message, completion }: AlertWebDialog) => {
|
|
10
|
-
globalAny?.alert?.(message);
|
|
11
|
-
completion?.();
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const showNativeAlertDialog = ({
|
|
15
|
-
title,
|
|
16
|
-
message,
|
|
17
|
-
okButtonText,
|
|
18
|
-
completion,
|
|
19
|
-
}: AlertDialogType) => {
|
|
20
|
-
Alert.alert(title, message, [
|
|
21
|
-
{
|
|
22
|
-
text: okButtonText,
|
|
23
|
-
onPress: completion,
|
|
24
|
-
},
|
|
25
|
-
]);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const showAlertDialog = ({
|
|
29
|
-
title,
|
|
30
|
-
message,
|
|
31
|
-
okButtonText,
|
|
32
|
-
completion,
|
|
33
|
-
}: AlertDialogType) => {
|
|
34
|
-
if (isWeb()) {
|
|
35
|
-
showWebAlertDialog({ message, completion });
|
|
36
|
-
} else {
|
|
37
|
-
showNativeAlertDialog({
|
|
38
|
-
title,
|
|
39
|
-
message,
|
|
40
|
-
okButtonText,
|
|
41
|
-
completion,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// #endregion "Alert Dialog"
|
|
47
|
-
|
|
48
|
-
// #region "Confirmation Dialog"
|
|
49
|
-
|
|
50
|
-
const showWebDialog = ({
|
|
51
|
-
message,
|
|
52
|
-
confirmCompletion,
|
|
53
|
-
cancelCompletion,
|
|
54
|
-
}: WebConfirmationDialog) => {
|
|
55
|
-
const isConfirmed = globalAny?.confirm?.(message);
|
|
56
|
-
|
|
57
|
-
if (isConfirmed) {
|
|
58
|
-
confirmCompletion?.();
|
|
59
|
-
} else {
|
|
60
|
-
cancelCompletion?.();
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const showNativeDialog = ({
|
|
65
|
-
title,
|
|
66
|
-
message,
|
|
67
|
-
okButtonText,
|
|
68
|
-
cancelButtonText,
|
|
69
|
-
confirmCompletion,
|
|
70
|
-
cancelCompletion,
|
|
71
|
-
}: ConfirmationDialog) => {
|
|
72
|
-
Alert.alert(title, message, [
|
|
73
|
-
{
|
|
74
|
-
text: cancelButtonText,
|
|
75
|
-
onPress: cancelCompletion,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
text: okButtonText,
|
|
79
|
-
style: "destructive",
|
|
80
|
-
onPress: confirmCompletion,
|
|
81
|
-
},
|
|
82
|
-
]);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const handleCustomDialog = (data) => {
|
|
86
|
-
const {
|
|
87
|
-
showDialog,
|
|
88
|
-
hideDialog,
|
|
89
|
-
setConfirmAction,
|
|
90
|
-
setCancelAction,
|
|
91
|
-
setMessages,
|
|
92
|
-
} = confirmationDialogStore.getState();
|
|
93
|
-
|
|
94
|
-
setMessages(data.messages);
|
|
95
|
-
|
|
96
|
-
if (data?.cancelCompletion) {
|
|
97
|
-
setCancelAction(() => {
|
|
98
|
-
data.cancelCompletion();
|
|
99
|
-
hideDialog();
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (data?.confirmCompletion) {
|
|
104
|
-
setConfirmAction(() => {
|
|
105
|
-
data.confirmCompletion();
|
|
106
|
-
hideDialog();
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
showDialog();
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const showConfirmationDialog = ({
|
|
114
|
-
title,
|
|
115
|
-
message,
|
|
116
|
-
okButtonText,
|
|
117
|
-
cancelButtonText,
|
|
118
|
-
confirmCompletion,
|
|
119
|
-
cancelCompletion,
|
|
120
|
-
}: CustomConfirmationDialog): void => {
|
|
121
|
-
if (isWeb()) {
|
|
122
|
-
if (cancelCompletion) {
|
|
123
|
-
handleCustomDialog({
|
|
124
|
-
messages: {
|
|
125
|
-
title,
|
|
126
|
-
message,
|
|
127
|
-
okButtonText,
|
|
128
|
-
cancelButtonText,
|
|
129
|
-
},
|
|
130
|
-
confirmCompletion,
|
|
131
|
-
cancelCompletion,
|
|
132
|
-
});
|
|
133
|
-
} else {
|
|
134
|
-
showWebDialog({ message, confirmCompletion, cancelCompletion });
|
|
135
|
-
}
|
|
136
|
-
} else {
|
|
137
|
-
showNativeDialog({
|
|
138
|
-
title,
|
|
139
|
-
message,
|
|
140
|
-
okButtonText,
|
|
141
|
-
cancelButtonText,
|
|
142
|
-
confirmCompletion,
|
|
143
|
-
cancelCompletion,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// #endregion "Confirmation Dialog"
|
|
1
|
+
export { showAlertDialog, showConfirmationDialog } from "./alert";
|