@applicaster/zapp-react-native-utils 13.0.0-alpha.6234681660 → 13.0.0-alpha.6400875052
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/actionsExecutor/ActionExecutorContext.tsx +2 -1
- package/appUtils/HooksManager/Hook.ts +4 -0
- package/appUtils/HooksManager/index.ts +2 -0
- package/dateUtils/index.ts +2 -0
- package/focusManager/FocusManager.ts +3 -1
- package/focusManager/index.ts +4 -30
- package/modalState/index.ts +32 -2
- package/package.json +2 -2
- package/reactHooks/advertising/index.ts +5 -5
- package/reactHooks/navigation/useRoute.ts +2 -2
- 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/types.ts +11 -0
|
@@ -274,7 +274,7 @@ export function withActionExecutor(Component) {
|
|
|
274
274
|
useEffect(() => {
|
|
275
275
|
return _actionExecutor.registerAction(
|
|
276
276
|
"navigateToScreen",
|
|
277
|
-
async (action: ActionType,
|
|
277
|
+
async (action: ActionType, context?: Record<string, any>) => {
|
|
278
278
|
const screenType = action.options?.typeMapping;
|
|
279
279
|
|
|
280
280
|
if (!screenType) {
|
|
@@ -301,6 +301,7 @@ export function withActionExecutor(Component) {
|
|
|
301
301
|
return ActionResult.Error;
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
context?.callback?.({ success: false, error: null, abort: true });
|
|
304
305
|
navigator.replace(river);
|
|
305
306
|
|
|
306
307
|
return ActionResult.Success;
|
|
@@ -65,6 +65,10 @@ export class Hook implements HookInterface {
|
|
|
65
65
|
event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
|
|
66
66
|
...args
|
|
67
67
|
) {
|
|
68
|
+
if (this.state === hookState(HOOKS_EVENTS.CANCEL)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
this.state = hookState(event);
|
|
69
73
|
this.manager.subscriber.invokeHandler(event, ...args);
|
|
70
74
|
}
|
|
@@ -269,6 +269,7 @@ export function HooksManager({
|
|
|
269
269
|
payload = initialPayload,
|
|
270
270
|
callback: callbackArg,
|
|
271
271
|
cancelled,
|
|
272
|
+
abort,
|
|
272
273
|
}) {
|
|
273
274
|
let callback = callbackArg;
|
|
274
275
|
|
|
@@ -308,6 +309,7 @@ export function HooksManager({
|
|
|
308
309
|
hookPlugin.setStateAndNotify(HOOKS_EVENTS.CANCEL, {
|
|
309
310
|
hookPlugin,
|
|
310
311
|
payload,
|
|
312
|
+
abort,
|
|
311
313
|
});
|
|
312
314
|
|
|
313
315
|
const isHookInHomescreen = payload?.home;
|
package/dateUtils/index.ts
CHANGED
|
@@ -2,10 +2,12 @@ import dayjs from "dayjs";
|
|
|
2
2
|
import utc from "dayjs/plugin/utc";
|
|
3
3
|
import timezone from "dayjs/plugin/timezone";
|
|
4
4
|
import isoWeek from "dayjs/plugin/isoWeek";
|
|
5
|
+
import duration from "dayjs/plugin/duration";
|
|
5
6
|
|
|
6
7
|
// Extend dayjs with plugins
|
|
7
8
|
dayjs.extend(utc);
|
|
8
9
|
dayjs.extend(timezone);
|
|
9
10
|
dayjs.extend(isoWeek);
|
|
11
|
+
dayjs.extend(duration);
|
|
10
12
|
|
|
11
13
|
export { dayjs };
|
|
@@ -227,7 +227,9 @@ class FocusManager {
|
|
|
227
227
|
|
|
228
228
|
const nextNextFocus = FocusManager.getNextFocusable(direction, nextFocus);
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
if (nextNextFocus) {
|
|
231
|
+
FocusManager.instance.setFocus(nextNextFocus, options);
|
|
232
|
+
}
|
|
231
233
|
} else {
|
|
232
234
|
FocusManager.instance.setFocusLocal(nextFocus);
|
|
233
235
|
|
package/focusManager/index.ts
CHANGED
|
@@ -8,8 +8,6 @@ import { isNilOrEmpty } from "../reactUtils/helpers";
|
|
|
8
8
|
import { isAndroidTVPlatform } from "../reactUtils";
|
|
9
9
|
import { noop } from "../functionUtils";
|
|
10
10
|
|
|
11
|
-
const EMPTY_GROUP_COMPONENT = "empty_group_component";
|
|
12
|
-
|
|
13
11
|
export function useFocusManager() {
|
|
14
12
|
return focusManager;
|
|
15
13
|
}
|
|
@@ -76,14 +74,6 @@ export function useFocusEffect(onFocus, focusWatcher) {
|
|
|
76
74
|
}, focusWatcher);
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
export function shouldShowEmptyGroup(component) {
|
|
80
|
-
return (
|
|
81
|
-
component?.ui_components?.filter(
|
|
82
|
-
({ component_type }) => component_type === EMPTY_GROUP_COMPONENT
|
|
83
|
-
)?.length > 0
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
77
|
export const isFocusable = (component: ZappEntry | ZappUIComponent | any) =>
|
|
88
78
|
R.tryCatch(
|
|
89
79
|
R.compose(
|
|
@@ -101,6 +91,7 @@ type Props = {
|
|
|
101
91
|
|
|
102
92
|
export const useIsFocusable = (props: Props): void => {
|
|
103
93
|
const { component, zappPipesData } = props;
|
|
94
|
+
|
|
104
95
|
const { setIsFocusable } = useFocusable();
|
|
105
96
|
|
|
106
97
|
const componentCellsFocusable = toBooleanWithDefaultTrue(
|
|
@@ -117,33 +108,18 @@ export const useIsFocusable = (props: Props): void => {
|
|
|
117
108
|
isNilOrEmpty(zappPipesData?.data) ||
|
|
118
109
|
isNilOrEmpty(zappPipesData?.data?.entry);
|
|
119
110
|
|
|
120
|
-
const hasNoUIComponents = isNilOrEmpty(component?.ui_components);
|
|
121
|
-
|
|
122
111
|
const hasDataError = !!zappPipesData?.error;
|
|
123
112
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
const isGallery = component?.component_type === "gallery-qb";
|
|
127
|
-
|
|
128
|
-
const isGroup = component?.component_type === "group-qb";
|
|
129
|
-
|
|
130
|
-
const isHiddenDueToEmptyData =
|
|
131
|
-
!isLoadingData && hasNoData && hideIfDataEmpty && !hasEmptyGroup;
|
|
132
|
-
|
|
133
|
-
const isEmptyGroup = isGroup && hasNoUIComponents;
|
|
113
|
+
const isHiddenDueToEmptyData = !isLoadingData && hasNoData && hideIfDataEmpty;
|
|
134
114
|
|
|
135
115
|
const defaultFocusableLogic =
|
|
136
|
-
componentCellsFocusable &&
|
|
137
|
-
(!hasNoData || !hideIfDataEmpty) &&
|
|
138
|
-
!isEmptyGroup;
|
|
116
|
+
componentCellsFocusable && (!hasNoData || !hideIfDataEmpty);
|
|
139
117
|
|
|
140
118
|
React.useEffect(() => {
|
|
141
119
|
if (isAndroidTVPlatform()) {
|
|
142
120
|
let isFocusableNew = false;
|
|
143
121
|
|
|
144
|
-
if (
|
|
145
|
-
isFocusableNew = true;
|
|
146
|
-
} else if (isFocusable(component)) {
|
|
122
|
+
if (isFocusable(component)) {
|
|
147
123
|
isFocusableNew = defaultFocusableLogic;
|
|
148
124
|
}
|
|
149
125
|
|
|
@@ -152,9 +128,7 @@ export const useIsFocusable = (props: Props): void => {
|
|
|
152
128
|
}, [
|
|
153
129
|
defaultFocusableLogic,
|
|
154
130
|
isHiddenDueToEmptyData,
|
|
155
|
-
isGallery,
|
|
156
131
|
setIsFocusable,
|
|
157
132
|
hasDataError,
|
|
158
|
-
hasEmptyGroup,
|
|
159
133
|
]);
|
|
160
134
|
};
|
package/modalState/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useStore, createStore } from "zustand";
|
|
2
2
|
|
|
3
3
|
interface ModalState {
|
|
4
4
|
visible: boolean;
|
|
@@ -25,7 +25,7 @@ const initialModalState: ModalState = {
|
|
|
25
25
|
props: {},
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export const
|
|
28
|
+
export const modalStore = createStore<ModalStore>((set) => ({
|
|
29
29
|
modalState: initialModalState,
|
|
30
30
|
setModalState: (newState) =>
|
|
31
31
|
set((state) => ({
|
|
@@ -51,3 +51,33 @@ export const useModalStore = create<ModalStore>((set) => ({
|
|
|
51
51
|
}),
|
|
52
52
|
dismissModal: () => set(() => ({ modalState: initialModalState })),
|
|
53
53
|
}));
|
|
54
|
+
|
|
55
|
+
export const useModalStore = <T>(selector: (state: ModalStore) => T) =>
|
|
56
|
+
useStore(modalStore, selector);
|
|
57
|
+
|
|
58
|
+
export const openModal = modalStore.getInitialState().openModal;
|
|
59
|
+
|
|
60
|
+
export const dismissModal = modalStore.getInitialState().dismissModal;
|
|
61
|
+
|
|
62
|
+
export const openBottomSheetModal = ({
|
|
63
|
+
ModalBottomSheetContent,
|
|
64
|
+
modalBottomSheetContentProps,
|
|
65
|
+
props = {},
|
|
66
|
+
options = {},
|
|
67
|
+
}: OpenModalBottomSheetArgs) => {
|
|
68
|
+
openModal({
|
|
69
|
+
item: {
|
|
70
|
+
ModalBottomSheetContent,
|
|
71
|
+
modalBottomSheetContentProps,
|
|
72
|
+
},
|
|
73
|
+
props,
|
|
74
|
+
options: {
|
|
75
|
+
animationType: "none",
|
|
76
|
+
animated: false,
|
|
77
|
+
...options,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const useModalStoreState = (): ModalState =>
|
|
83
|
+
useModalStore<ModalState>((state) => state.modalState);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.6400875052",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@applicaster/applicaster-types": "13.0.0-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "13.0.0-alpha.6400875052",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
@@ -5,6 +5,7 @@ import * as R from "ramda";
|
|
|
5
5
|
import { useNavigation } from "../navigation";
|
|
6
6
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
7
7
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
8
|
+
import { dismissModal, openModal } from "../../modalState";
|
|
8
9
|
|
|
9
10
|
const GOOGLE_ADS_IDENTIFIER = "google-admob-ads-qb";
|
|
10
11
|
|
|
@@ -14,9 +15,8 @@ const ModalContainer = platformSelect({
|
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
export function useAdvertisingInterstitial() {
|
|
17
|
-
const
|
|
18
|
+
const { screenData, currentRoute } = useNavigation();
|
|
18
19
|
const { plugins } = usePickFromState();
|
|
19
|
-
const { screenData } = navigator;
|
|
20
20
|
|
|
21
21
|
return useEffect(() => {
|
|
22
22
|
// TODD: typing problem: fix any type
|
|
@@ -26,7 +26,7 @@ export function useAdvertisingInterstitial() {
|
|
|
26
26
|
plugins
|
|
27
27
|
);
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
openModal({
|
|
30
30
|
item: {},
|
|
31
31
|
options: {
|
|
32
32
|
ModalContainer,
|
|
@@ -36,11 +36,11 @@ export function useAdvertisingInterstitial() {
|
|
|
36
36
|
screenType: "hooks",
|
|
37
37
|
screenData: {
|
|
38
38
|
payload: screenData,
|
|
39
|
-
callback:
|
|
39
|
+
callback: dismissModal,
|
|
40
40
|
hookPlugin: GoogleAdsPlugin,
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
}, [
|
|
45
|
+
}, [currentRoute, screenData?.id]);
|
|
46
46
|
}
|
|
@@ -11,7 +11,7 @@ import { getTargetScreenData } from "../screen/useTargetScreenData";
|
|
|
11
11
|
import { useHookModalScreenData } from "../hookModal/hooks/useHookModalScreenData";
|
|
12
12
|
|
|
13
13
|
import { useNavigation } from "./useNavigation";
|
|
14
|
-
import {
|
|
14
|
+
import { useModalStoreState } from "../../modalState";
|
|
15
15
|
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
16
16
|
import { usePathname } from "./usePathname";
|
|
17
17
|
|
|
@@ -43,7 +43,7 @@ export const useRoute = (): {
|
|
|
43
43
|
"contentTypes",
|
|
44
44
|
]);
|
|
45
45
|
|
|
46
|
-
const
|
|
46
|
+
const modalState = useModalStoreState();
|
|
47
47
|
|
|
48
48
|
const modalScreenData = modalState.screen;
|
|
49
49
|
|
package/utils/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
### ramda replacement utils
|
|
2
|
+
|
|
3
|
+
See contribution guide below
|
|
4
|
+
|
|
5
|
+
## Reference
|
|
6
|
+
|
|
7
|
+
Prefer non-fp variant as it more performant - if refactoring assumes you need more efforts rewrite ramda sample to lodash and it can be easily replaced with lodash-fp - use lodash-fp.
|
|
8
|
+
|
|
9
|
+
### Ramda alternatives:
|
|
10
|
+
|
|
11
|
+
Custom
|
|
12
|
+
- `splitEvery` => `chunk`
|
|
13
|
+
- `times` => `times`
|
|
14
|
+
|
|
15
|
+
From `lodash`
|
|
16
|
+
- `clone` => `clone`
|
|
17
|
+
- `flatten` => `flatten`
|
|
18
|
+
- `drop` => `drop`
|
|
19
|
+
- `length` => `size`
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Contribution
|
|
23
|
+
|
|
24
|
+
To add new helper function as ramda replacement
|
|
25
|
+
|
|
26
|
+
1. Search for replacement ( you can use lodash or pure JS solution), arguments should match with Ramda definition (for easier transition).
|
|
27
|
+
2. Add new file if needed, add test, update exports in index file. 2.1. Make sure it's well-typed.
|
|
28
|
+
3. If the function can-be reexported from other 3rd party lib - update index.ts to re-export it.
|
|
29
|
+
4. Make sure README is updated and contains reference for newly added function.
|
|
30
|
+
5. You can use AI's help. Use query like 'lodash & lodash/fp equivalent of Ramda's R.clone function' to get an options you can use.
|
package/utils/chunk.ts
ADDED
package/utils/index.ts
ADDED
package/utils/times.ts
ADDED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
2
2
|
import { isNilOrEmpty } from "../reactUtils/helpers";
|
|
3
3
|
import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
4
|
+
import {
|
|
5
|
+
StorageOwnedValues,
|
|
6
|
+
NamespaceValues,
|
|
7
|
+
StorageValuesToRemove,
|
|
8
|
+
StorageValuesToAdd,
|
|
9
|
+
} from "./types";
|
|
4
10
|
|
|
5
11
|
const defaultOwnedKey = "owned_keys";
|
|
6
12
|
const DEFAULT_NAMESPACE = "applicaster.v2";
|