@applicaster/zapp-react-native-utils 14.0.0-alpha.4274952546 → 14.0.0-alpha.4517121861
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 +1 -1
- package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
- package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
- package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +1 -2
- package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
- package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
- package/analyticsUtils/events.ts +8 -0
- package/analyticsUtils/index.tsx +4 -3
- package/analyticsUtils/manager.ts +1 -1
- package/appUtils/accessibilityManager/index.ts +3 -3
- package/focusManager/FocusManager.ts +26 -16
- package/focusManager/Tree.ts +25 -21
- package/focusManager/__tests__/FocusManager.test.ts +50 -8
- package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
- package/package.json +2 -2
- package/playerUtils/getPlayerActionButtons.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +13 -12
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +88 -39
- package/reactHooks/feed/useBatchLoading.ts +1 -1
- package/reactHooks/feed/usePipesCacheReset.ts +1 -1
- package/reactHooks/navigation/index.ts +2 -2
- package/reactHooks/navigation/useIsScreenActive.ts +9 -5
- package/reactHooks/screen/useScreenContext.ts +1 -1
- package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
- package/riverComponetsMeasurementProvider/index.tsx +1 -1
- package/services/js2native.ts +1 -0
- package/testUtils/index.tsx +8 -7
- package/time/BackgroundTimer.ts +5 -3
- package/utils/index.ts +4 -0
|
@@ -4,9 +4,12 @@ import {
|
|
|
4
4
|
ANALYTICS_COMPONENT_EVENTS,
|
|
5
5
|
ANALYTICS_CORE_EVENTS,
|
|
6
6
|
ANALYTICS_ENTRY_EVENTS,
|
|
7
|
+
ANALYTICS_PREFERENCES_EVENTS,
|
|
7
8
|
DOWNLOADS_EVENTS,
|
|
8
9
|
} from "../events";
|
|
9
10
|
import { isEmptyOrNil } from "../../cellUtils";
|
|
11
|
+
import { get } from "lodash";
|
|
12
|
+
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
10
13
|
|
|
11
14
|
export enum OfflineItemState {
|
|
12
15
|
notExist = "NOT_EXISTS",
|
|
@@ -102,6 +105,84 @@ export function eventForComponent(
|
|
|
102
105
|
return analyticsProps;
|
|
103
106
|
}
|
|
104
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Checks if an item is currently selected in localStorage based on its actions
|
|
110
|
+
* @param item - The item to check
|
|
111
|
+
* @returns boolean indicating if the item is currently selected
|
|
112
|
+
*/
|
|
113
|
+
function isItemPreviouslySelected(item: any): boolean {
|
|
114
|
+
const actions = item?.extensions?.tap_actions?.actions;
|
|
115
|
+
|
|
116
|
+
if (!actions) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const localStorageAction = actions.find(
|
|
121
|
+
(action) => action?.type === "localStorageToggleFlag"
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
if (!localStorageAction?.options?.key) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const keyNamespace = localStorageAction.options.key;
|
|
129
|
+
|
|
130
|
+
const tag = localStorageAction.options?.selector
|
|
131
|
+
? get(item, localStorageAction.options.selector)
|
|
132
|
+
: (item.extensions?.tag ?? item.id);
|
|
133
|
+
|
|
134
|
+
if (!tag) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const multiSelectProvider =
|
|
140
|
+
StorageMultiSelectProvider.getProvider(keyNamespace);
|
|
141
|
+
|
|
142
|
+
const selectedItems = multiSelectProvider.getSelectedItems();
|
|
143
|
+
|
|
144
|
+
return selectedItems.includes(tag);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function getLocalStorageSetPayload(extraProps) {
|
|
151
|
+
const { item } = extraProps;
|
|
152
|
+
|
|
153
|
+
const hasLocalStorageSetAction = item?.extensions?.tap_actions?.actions?.some(
|
|
154
|
+
(action) => action?.type === "localStorageSet"
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
if (!hasLocalStorageSetAction) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
[ANALYTICS_PREFERENCES_EVENTS.ITEM_SELECTED_STATUS]: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function getLocalStorageToggleFlagPayload(extraProps) {
|
|
167
|
+
const { item } = extraProps;
|
|
168
|
+
|
|
169
|
+
const hasLocalStorageToggleAction =
|
|
170
|
+
item?.extensions?.tap_actions?.actions?.some(
|
|
171
|
+
(action) => action?.type === "localStorageToggleFlag"
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (!hasLocalStorageToggleAction) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const previouslySelected = isItemPreviouslySelected(item);
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
[ANALYTICS_PREFERENCES_EVENTS.ITEM_SELECTED_STATUS]: !previouslySelected,
|
|
182
|
+
[ANALYTICS_PREFERENCES_EVENTS.PREVIOUS_SELECTED_STATE]: previouslySelected,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
105
186
|
export function playEventForType(item) {
|
|
106
187
|
const itemType = item?.type && item.type?.value;
|
|
107
188
|
|
|
@@ -4,7 +4,7 @@ import { postAnalyticEvent } from "../manager";
|
|
|
4
4
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
5
5
|
|
|
6
6
|
type SendHeaderClickEventProps = {
|
|
7
|
-
extraProps:
|
|
7
|
+
extraProps: ExtraProps;
|
|
8
8
|
component?: ZappUIComponent;
|
|
9
9
|
zappPipesData?: ZappPipesData;
|
|
10
10
|
item?: ZappEntry;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/// <reference types="../../" />
|
|
2
1
|
import { log_error, log_debug } from "../logger";
|
|
3
2
|
import { replaceAnalyticsPropsNils } from "./helper";
|
|
4
3
|
import { postAnalyticEvent } from "../manager";
|
|
5
4
|
|
|
6
5
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
7
6
|
|
|
8
|
-
type AnalyticsDefaultHelperProperties = {
|
|
7
|
+
declare type AnalyticsDefaultHelperProperties = {
|
|
9
8
|
analyticsScreenData: AnalyticsScreenProperties;
|
|
10
9
|
extraProps: any;
|
|
11
10
|
props;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { log_error, log_debug } from "../logger";
|
|
2
|
-
|
|
3
|
-
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
4
|
-
|
|
2
|
+
import { ANALYTICS_CORE_EVENTS, ACTION_TYPE } from "../events";
|
|
5
3
|
import { postAnalyticEvent } from "../manager";
|
|
6
4
|
import {
|
|
7
5
|
replaceAnalyticsPropsNils,
|
|
8
6
|
eventForEntry,
|
|
9
7
|
eventForComponent,
|
|
10
8
|
extensionsEvents,
|
|
9
|
+
getLocalStorageSetPayload,
|
|
10
|
+
getLocalStorageToggleFlagPayload,
|
|
11
11
|
} from "./helper";
|
|
12
12
|
|
|
13
13
|
declare type AnalyticsDefaultHelperProperties = {
|
|
@@ -26,7 +26,16 @@ export const sendOnClickEvent = ({
|
|
|
26
26
|
const castedExtraProps: ExtraProps = extraProps;
|
|
27
27
|
const componentData = component || extraProps.component;
|
|
28
28
|
const data = zappPipesData || extraProps.zappPipesData;
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+
const actionCellPayload =
|
|
31
|
+
extraProps?.item?.type?.value === ACTION_TYPE
|
|
32
|
+
? getLocalStorageSetPayload(extraProps) ||
|
|
33
|
+
getLocalStorageToggleFlagPayload(extraProps)
|
|
34
|
+
: null;
|
|
35
|
+
|
|
36
|
+
const eventName = actionCellPayload
|
|
37
|
+
? ANALYTICS_CORE_EVENTS.TAP_SELECTABLE_CELL
|
|
38
|
+
: ANALYTICS_CORE_EVENTS.TAP_CELL;
|
|
30
39
|
|
|
31
40
|
if (!analyticsScreenData) {
|
|
32
41
|
log_error(
|
|
@@ -44,6 +53,7 @@ export const sendOnClickEvent = ({
|
|
|
44
53
|
...replaceAnalyticsPropsNils({
|
|
45
54
|
...analyticsScreenData,
|
|
46
55
|
}),
|
|
56
|
+
...actionCellPayload,
|
|
47
57
|
};
|
|
48
58
|
|
|
49
59
|
if (analyticsCustomProperties) {
|
|
@@ -3,8 +3,22 @@ import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
|
3
3
|
|
|
4
4
|
jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
|
|
5
5
|
isWeb: jest.fn(),
|
|
6
|
+
platformSelect: jest.fn(
|
|
7
|
+
(options) => options.android || options.ios || options.web
|
|
8
|
+
),
|
|
6
9
|
}));
|
|
7
10
|
|
|
11
|
+
jest.mock(
|
|
12
|
+
"@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider",
|
|
13
|
+
() => ({
|
|
14
|
+
StorageMultiSelectProvider: {
|
|
15
|
+
getProvider: jest.fn(() => ({
|
|
16
|
+
getSelectedItems: jest.fn(() => []),
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
|
|
8
22
|
const mock_postAnalyticEvent = jest.fn();
|
|
9
23
|
const mock_startAnalyticsTimedEvent = jest.fn();
|
|
10
24
|
const mock_endAnalyticsTimedEvent = jest.fn();
|
package/analyticsUtils/events.ts
CHANGED
|
@@ -17,8 +17,11 @@ export const SCREEN_VIEW_EVENTS = {
|
|
|
17
17
|
TIME_ON_SCREEN: "time_on_screen",
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
export const ACTION_TYPE = "action";
|
|
21
|
+
|
|
20
22
|
export const TAPPING_EVENTS = {
|
|
21
23
|
TAP_CELL: "tap_cell",
|
|
24
|
+
TAP_SELECTABLE_CELL: "tap_selectable_cell",
|
|
22
25
|
TAP_MENU: "tap_menu",
|
|
23
26
|
TAP_NAVBAR_BACK_BUTTON: "tap_navbar_back_button",
|
|
24
27
|
};
|
|
@@ -99,6 +102,11 @@ export const ANALYTICS_COMPONENT_EVENTS = {
|
|
|
99
102
|
COMPONENT_SOURCE: "component_source",
|
|
100
103
|
};
|
|
101
104
|
|
|
105
|
+
export const ANALYTICS_PREFERENCES_EVENTS = {
|
|
106
|
+
ITEM_SELECTED_STATUS: "item_selected_status",
|
|
107
|
+
PREVIOUS_SELECTED_STATE: "previous_selected_state",
|
|
108
|
+
};
|
|
109
|
+
|
|
102
110
|
// ---------------- EVENTS ---------------------
|
|
103
111
|
export const AD_EVENT = {
|
|
104
112
|
ad_break_start: "player_ad_break_start",
|
package/analyticsUtils/index.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="@applicaster/zapp-react-native-utils" />
|
|
1
2
|
import * as R from "ramda";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
@@ -30,7 +31,7 @@ import { ANALYTICS_CORE_EVENTS } from "./events";
|
|
|
30
31
|
import { noop } from "../functionUtils";
|
|
31
32
|
|
|
32
33
|
type ComponentWithChildrenProps = {
|
|
33
|
-
children: React.
|
|
34
|
+
children: React.ReactChildren;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
export function sendSelectCellEvent(item, component, headerTitle, itemIndex) {
|
|
@@ -119,11 +120,11 @@ export function getAnalyticsFunctions({
|
|
|
119
120
|
export const AnalyticsContext =
|
|
120
121
|
React.createContext<GetAnalyticsFunctions>(noop);
|
|
121
122
|
|
|
122
|
-
export function AnalyticsProvider(
|
|
123
|
+
export function AnalyticsProvider(props: ComponentWithChildrenProps) {
|
|
123
124
|
return (
|
|
124
125
|
// @ts-ignore - this is a valid context provider
|
|
125
126
|
<AnalyticsContext.Provider value={getAnalyticsFunctions}>
|
|
126
|
-
{children}
|
|
127
|
+
{props?.children}
|
|
127
128
|
</AnalyticsContext.Provider>
|
|
128
129
|
);
|
|
129
130
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { NativeModules } from "react-native";
|
|
4
|
-
import { ANALYTICS_CORE_EVENTS } from "
|
|
4
|
+
import { ANALYTICS_CORE_EVENTS } from "@applicaster/zapp-react-native-utils/analyticsUtils/events";
|
|
5
5
|
|
|
6
6
|
import { analyticsUtilsLogger } from "./logger";
|
|
7
7
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BehaviorSubject } from "rxjs";
|
|
2
2
|
import { accessibilityManagerLogger as logger } from "./logger";
|
|
3
|
-
import { TTSManager } from "../platform
|
|
3
|
+
import { TTSManager } from "../platform";
|
|
4
4
|
import { BUTTON_ACCESSIBILITY_KEYS } from "./const";
|
|
5
5
|
import { AccessibilityRole } from "react-native";
|
|
6
|
-
import
|
|
6
|
+
import { toString } from "../../utils";
|
|
7
7
|
|
|
8
8
|
export class AccessibilityManager {
|
|
9
9
|
private static _instance: AccessibilityManager | null = null;
|
|
@@ -137,7 +137,7 @@ export class AccessibilityManager {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
public getButtonAccessibilityProps(name: string): AccessibilityProps {
|
|
140
|
-
const buttonName =
|
|
140
|
+
const buttonName = toString(name);
|
|
141
141
|
|
|
142
142
|
const buttonConfig = BUTTON_ACCESSIBILITY_KEYS[buttonName];
|
|
143
143
|
|
|
@@ -176,18 +176,30 @@ class FocusManager {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
registerFocusable(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
isFocusableCell
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
registerFocusable({
|
|
180
|
+
touchableRef,
|
|
181
|
+
parentFocusableRef,
|
|
182
|
+
isFocusableCell,
|
|
183
|
+
parentFocusableId,
|
|
184
|
+
}: {
|
|
185
|
+
touchableRef: FocusManager.TouchableReactRef;
|
|
186
|
+
parentFocusableRef: FocusManager.TouchableReactRef;
|
|
187
|
+
isFocusableCell: boolean;
|
|
188
|
+
parentFocusableId: string;
|
|
189
|
+
}) {
|
|
190
|
+
const focusableId = getFocusableId(touchableRef);
|
|
191
|
+
|
|
185
192
|
const focusableComponent = FocusManager.findFocusable(focusableId);
|
|
186
193
|
|
|
187
|
-
if (!focusableComponent &&
|
|
188
|
-
this.focusableComponents.push(
|
|
194
|
+
if (!focusableComponent && touchableRef) {
|
|
195
|
+
this.focusableComponents.push(touchableRef);
|
|
189
196
|
|
|
190
|
-
this.tree.add(
|
|
197
|
+
this.tree.add(
|
|
198
|
+
touchableRef,
|
|
199
|
+
parentFocusableRef,
|
|
200
|
+
isFocusableCell,
|
|
201
|
+
parentFocusableId
|
|
202
|
+
);
|
|
191
203
|
} else {
|
|
192
204
|
logger.warning("Focusable component already registered", {
|
|
193
205
|
id: focusableId,
|
|
@@ -243,12 +255,10 @@ class FocusManager {
|
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
blurPrevious(options?: FocusManager.Android.CallbackOptions) {
|
|
246
|
-
|
|
247
|
-
FocusManager.instance.prevFocused
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
);
|
|
251
|
-
}
|
|
258
|
+
FocusManager.instance.prevFocused?.onBlur?.(
|
|
259
|
+
FocusManager.instance.prevFocused,
|
|
260
|
+
options ?? {} // Adding fallback to avoid potential regression caused by #7509
|
|
261
|
+
);
|
|
252
262
|
}
|
|
253
263
|
|
|
254
264
|
onDisableFocusChange = (id) => {
|
|
@@ -269,7 +279,7 @@ class FocusManager {
|
|
|
269
279
|
|
|
270
280
|
if (nextFocus) {
|
|
271
281
|
// HACK: hack to fix the hack below
|
|
272
|
-
// HACK: putting call to the end of the event loop so the next component has a
|
|
282
|
+
// HACK: putting call to the end of the event loop so the next component has a chance to be registered
|
|
273
283
|
setTimeout(() => {
|
|
274
284
|
FocusManager.instance.setFocus(nextFocus, {
|
|
275
285
|
direction: "down",
|
package/focusManager/Tree.ts
CHANGED
|
@@ -8,37 +8,41 @@ export class Tree {
|
|
|
8
8
|
this.tree = focusManagerTree;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
add(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
add(
|
|
12
|
+
touchableRef: FocusManager.TouchableReactRef,
|
|
13
|
+
parentFocusableRef: FocusManager.TouchableReactRef,
|
|
14
|
+
isFocusableCell: boolean,
|
|
15
|
+
parentFocusableId: string
|
|
16
|
+
) {
|
|
17
|
+
const focusableId = getFocusableId(touchableRef);
|
|
18
|
+
const parentId = getFocusableId(parentFocusableRef) || parentFocusableId;
|
|
14
19
|
const focusableComponentInTree = this.find(focusableId);
|
|
15
20
|
|
|
16
21
|
// update node if it already exists
|
|
17
22
|
if (focusableComponentInTree) {
|
|
18
|
-
focusableComponentInTree.updateNode(
|
|
23
|
+
focusableComponentInTree.updateNode(touchableRef);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
if (!this.find(parentId)) {
|
|
27
|
+
// create temporary node to the root of the tree
|
|
28
|
+
this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
|
|
29
|
+
}
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
const parentNode = this.find(parentId);
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
if (parentNode) {
|
|
34
|
+
if (focusableComponentInTree) {
|
|
35
|
+
focusableComponentInTree.isFocusableCell = isFocusableCell;
|
|
36
|
+
focusableComponentInTree.parentId = parentNode.id;
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
parentNode.addChild(focusableComponentInTree);
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
40
|
+
// remove root object from the list
|
|
41
|
+
this.tree = this.tree.filter(
|
|
42
|
+
(node) => node !== focusableComponentInTree
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
parentNode.addChild(touchableRef, focusableId, isFocusableCell);
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { focusManager } from "../FocusManager";
|
|
2
2
|
|
|
3
|
+
const isFocusableCell = true;
|
|
4
|
+
const parentFocusableId = "parentFocusableId";
|
|
5
|
+
|
|
3
6
|
const group = {
|
|
4
7
|
current: {
|
|
5
8
|
props: {
|
|
@@ -62,13 +65,47 @@ jest.useFakeTimers();
|
|
|
62
65
|
|
|
63
66
|
describe("FocusManager", () => {
|
|
64
67
|
beforeAll(() => {
|
|
65
|
-
focusManager.registerFocusable(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
focusManager.registerFocusable({
|
|
69
|
+
touchableRef: group,
|
|
70
|
+
parentFocusableRef: { current: null },
|
|
71
|
+
isFocusableCell,
|
|
72
|
+
parentFocusableId,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
focusManager.registerFocusable({
|
|
76
|
+
touchableRef: child1,
|
|
77
|
+
parentFocusableRef: group,
|
|
78
|
+
isFocusableCell,
|
|
79
|
+
parentFocusableId,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
focusManager.registerFocusable({
|
|
83
|
+
touchableRef: child2,
|
|
84
|
+
parentFocusableRef: group,
|
|
85
|
+
isFocusableCell,
|
|
86
|
+
parentFocusableId,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
focusManager.registerFocusable({
|
|
90
|
+
touchableRef: child3,
|
|
91
|
+
parentFocusableRef: child2,
|
|
92
|
+
isFocusableCell,
|
|
93
|
+
parentFocusableId,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
focusManager.registerFocusable({
|
|
97
|
+
touchableRef: child4,
|
|
98
|
+
parentFocusableRef: child2,
|
|
99
|
+
isFocusableCell,
|
|
100
|
+
parentFocusableId,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
focusManager.registerFocusable({
|
|
104
|
+
touchableRef: child5,
|
|
105
|
+
parentFocusableRef: child2,
|
|
106
|
+
isFocusableCell,
|
|
107
|
+
parentFocusableId,
|
|
108
|
+
});
|
|
72
109
|
});
|
|
73
110
|
|
|
74
111
|
it("focusManager should be defined", () => {
|
|
@@ -199,7 +236,12 @@ describe("FocusManager", () => {
|
|
|
199
236
|
});
|
|
200
237
|
|
|
201
238
|
it("focusManager registerFocusable should register", () => {
|
|
202
|
-
focusManager.registerFocusable(
|
|
239
|
+
focusManager.registerFocusable({
|
|
240
|
+
touchableRef: child5,
|
|
241
|
+
parentFocusableRef: child2,
|
|
242
|
+
isFocusableCell,
|
|
243
|
+
parentFocusableId,
|
|
244
|
+
});
|
|
203
245
|
|
|
204
246
|
expect(
|
|
205
247
|
focusManager.isFocusableChildOf(child5.current.props.id, child2)
|
|
@@ -2985,6 +2985,14 @@ function getPlayerConfiguration({ platform, version }) {
|
|
|
2985
2985
|
type: "uploader",
|
|
2986
2986
|
default: "",
|
|
2987
2987
|
},
|
|
2988
|
+
{
|
|
2989
|
+
key: "audio_player_background_image_overlay",
|
|
2990
|
+
label: "Background Image Overlay",
|
|
2991
|
+
label_tooltip:
|
|
2992
|
+
"Add a semi-transparent color overlay to improve text readability over the background image.",
|
|
2993
|
+
type: "color_picker_rgba",
|
|
2994
|
+
initial_value: "rgba(17, 17, 17, 0.5)",
|
|
2995
|
+
},
|
|
2988
2996
|
{
|
|
2989
2997
|
type: "text_input",
|
|
2990
2998
|
label: "Item Image Key",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.4517121861",
|
|
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": "14.0.0-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "14.0.0-alpha.4517121861",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
-
import { act, waitFor } from "@testing-library/react-native";
|
|
3
|
+
import { act, renderHook } from "@testing-library/react-hooks";
|
|
5
4
|
import { Provider } from "react-redux";
|
|
6
5
|
import configureStore from "redux-mock-store";
|
|
7
|
-
import { useTrackedView } from "../useTrackedView";
|
|
8
6
|
|
|
9
7
|
const mockUpdateComponentsPositions = jest.fn();
|
|
10
8
|
|
|
11
9
|
jest.mock(
|
|
12
10
|
"@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext",
|
|
13
11
|
() => ({
|
|
14
|
-
useScreenTrackedViewPositionsContext: jest.fn(
|
|
12
|
+
useScreenTrackedViewPositionsContext: jest.fn().mockReturnValue({
|
|
15
13
|
updateComponentsPositions: mockUpdateComponentsPositions,
|
|
16
14
|
value: {
|
|
17
15
|
"123": { componentId: "123", centerX: 0.4, centerY: 0.5 },
|
|
18
16
|
"124": { componentId: "124", centerX: 0.2, centerY: 0.3 },
|
|
19
17
|
},
|
|
20
|
-
})
|
|
18
|
+
}),
|
|
21
19
|
})
|
|
22
20
|
);
|
|
23
21
|
|
|
24
|
-
jest.useFakeTimers();
|
|
22
|
+
jest.useFakeTimers({ legacyFakeTimers: true });
|
|
25
23
|
|
|
26
24
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
27
25
|
|
|
@@ -34,8 +32,10 @@ const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
|
34
32
|
<Provider store={store}>{children}</Provider>
|
|
35
33
|
);
|
|
36
34
|
|
|
35
|
+
const { useTrackedView } = require("../useTrackedView");
|
|
36
|
+
|
|
37
37
|
describe("useTrackCurrentAutoScrollingElement", () => {
|
|
38
|
-
it("should update position for selected component - onViewportEnter",
|
|
38
|
+
it("should update position for selected component - onViewportEnter", () => {
|
|
39
39
|
const { result } = renderHook(() => useTrackedView("123"), {
|
|
40
40
|
wrapper: Wrapper,
|
|
41
41
|
});
|
|
@@ -46,13 +46,14 @@ describe("useTrackCurrentAutoScrollingElement", () => {
|
|
|
46
46
|
rect: { left: 1, right: 1, top: 1, bottom: 1 },
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
act(() => {
|
|
50
|
-
result.current.onPositionUpdated(mockRect);
|
|
49
|
+
act(async () => {
|
|
50
|
+
await result.current.onPositionUpdated(mockRect);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
// Fast-forward until all timers have been executed
|
|
54
|
+
jest.runAllTimers();
|
|
55
|
+
|
|
56
|
+
expect(result.current.inViewPort).toBe(true);
|
|
56
57
|
|
|
57
58
|
expect(mockUpdateComponentsPositions).toHaveBeenCalledWith(
|
|
58
59
|
"123",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { renderHook } from "@testing-library/react-hooks";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import * as reduxMockStore from "redux-mock-store";
|
|
3
|
+
import thunk from "redux-thunk";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import * as ReactRedux from "react-redux";
|
|
5
6
|
|
|
6
7
|
jest.mock("../../navigation");
|
|
7
8
|
|
|
@@ -12,18 +13,17 @@ jest.mock(
|
|
|
12
13
|
})
|
|
13
14
|
);
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const useBatchLoading = require("../useBatchLoading").useBatchLoading;
|
|
17
|
+
const allFeedsIsReady = require("../useBatchLoading").allFeedsIsReady;
|
|
18
|
+
|
|
19
|
+
const mockStore = reduxMockStore.default([thunk]);
|
|
20
|
+
|
|
21
|
+
const wrapper: React.FC<any> = ({ children, store }) => (
|
|
22
|
+
<ReactRedux.Provider store={store}>{children}</ReactRedux.Provider>
|
|
23
|
+
);
|
|
16
24
|
|
|
17
25
|
describe("useBatchLoading", () => {
|
|
18
|
-
const
|
|
19
|
-
{ data: { source: "url1" }, component_type: "any" },
|
|
20
|
-
{ data: { source: "url2" }, component_type: "any" },
|
|
21
|
-
{ data: { source: "url3" }, component_type: "any" },
|
|
22
|
-
{ data: { source: "url4" }, component_type: "any" },
|
|
23
|
-
{ data: { source: "url5" }, component_type: "any" },
|
|
24
|
-
{ data: { source: "url6" }, component_type: "any" },
|
|
25
|
-
// ... more items
|
|
26
|
-
];
|
|
26
|
+
const useDispatchSpy = jest.spyOn(ReactRedux, "useDispatch");
|
|
27
27
|
|
|
28
28
|
beforeAll(() => {
|
|
29
29
|
jest.useFakeTimers();
|
|
@@ -34,7 +34,7 @@ describe("useBatchLoading", () => {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it("loadPipesData start loading not started requests", () => {
|
|
37
|
-
const store = {
|
|
37
|
+
const store = mockStore({
|
|
38
38
|
zappPipes: {
|
|
39
39
|
url1: {
|
|
40
40
|
loading: true,
|
|
@@ -53,17 +53,29 @@ describe("useBatchLoading", () => {
|
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
test: "true",
|
|
56
|
-
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
57
59
|
|
|
58
60
|
const initialBatchSize = 3;
|
|
59
61
|
const riverId = "123";
|
|
60
62
|
|
|
63
|
+
const data = [
|
|
64
|
+
{ data: { source: "url1" } },
|
|
65
|
+
{ data: { source: "url2" } },
|
|
66
|
+
{ data: { source: "url3" } },
|
|
67
|
+
{ data: { source: "url4" } },
|
|
68
|
+
{ data: { source: "url5" } },
|
|
69
|
+
{ data: { source: "url6" } },
|
|
70
|
+
// ... more items
|
|
71
|
+
];
|
|
72
|
+
|
|
61
73
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
62
74
|
wrapper,
|
|
63
75
|
initialProps: { store },
|
|
64
76
|
});
|
|
65
77
|
|
|
66
|
-
const actions =
|
|
78
|
+
const actions = store.getActions();
|
|
67
79
|
|
|
68
80
|
expect(actions).toHaveLength(2);
|
|
69
81
|
|
|
@@ -79,7 +91,7 @@ describe("useBatchLoading", () => {
|
|
|
79
91
|
});
|
|
80
92
|
|
|
81
93
|
it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", () => {
|
|
82
|
-
const store = {
|
|
94
|
+
const store = mockStore({
|
|
83
95
|
zappPipes: {
|
|
84
96
|
url1: {
|
|
85
97
|
loading: false,
|
|
@@ -98,17 +110,31 @@ describe("useBatchLoading", () => {
|
|
|
98
110
|
},
|
|
99
111
|
},
|
|
100
112
|
test: "true",
|
|
101
|
-
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
102
116
|
|
|
103
117
|
const initialBatchSize = 3;
|
|
104
118
|
const riverId = "123";
|
|
105
119
|
|
|
120
|
+
const data = [
|
|
121
|
+
{ data: { source: "url1" } },
|
|
122
|
+
{ data: { source: "url2" } },
|
|
123
|
+
{ data: { source: "url3" } },
|
|
124
|
+
{ data: { source: "url4" } },
|
|
125
|
+
{ data: { source: "url5" } },
|
|
126
|
+
{ data: { source: "url6" } },
|
|
127
|
+
// ... more items
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
expect(useDispatchSpy).toBeCalledTimes(0);
|
|
131
|
+
|
|
106
132
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
107
133
|
wrapper,
|
|
108
134
|
initialProps: { store },
|
|
109
135
|
});
|
|
110
136
|
|
|
111
|
-
const actions =
|
|
137
|
+
const actions = store.getActions();
|
|
112
138
|
|
|
113
139
|
expect(actions).toHaveLength(1);
|
|
114
140
|
|
|
@@ -119,26 +145,38 @@ describe("useBatchLoading", () => {
|
|
|
119
145
|
});
|
|
120
146
|
|
|
121
147
|
it("loadPipesData has been called when no data cached", () => {
|
|
122
|
-
const store = {
|
|
148
|
+
const store = mockStore({
|
|
123
149
|
zappPipes: {},
|
|
124
150
|
test: "true",
|
|
125
|
-
};
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
126
154
|
|
|
127
155
|
const initialBatchSize = 3;
|
|
128
156
|
const riverId = "123";
|
|
129
157
|
|
|
158
|
+
const data = [
|
|
159
|
+
{ data: { source: "url1" } },
|
|
160
|
+
{ data: { source: "url2" } },
|
|
161
|
+
{ data: { source: "url3" } },
|
|
162
|
+
{ data: { source: "url4" } },
|
|
163
|
+
{ data: { source: "url5" } },
|
|
164
|
+
{ data: { source: "url6" } },
|
|
165
|
+
// ... more items
|
|
166
|
+
];
|
|
167
|
+
|
|
130
168
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
131
169
|
wrapper,
|
|
132
170
|
initialProps: { store },
|
|
133
171
|
});
|
|
134
172
|
|
|
135
|
-
const actions =
|
|
173
|
+
const actions = store.getActions();
|
|
136
174
|
|
|
137
175
|
expect(actions).toHaveLength(3);
|
|
138
176
|
});
|
|
139
177
|
|
|
140
178
|
it("initial batch ready when all initial items loaded", () => {
|
|
141
|
-
const store = {
|
|
179
|
+
const store = mockStore({
|
|
142
180
|
zappPipes: {
|
|
143
181
|
url1: {
|
|
144
182
|
loading: false,
|
|
@@ -156,11 +194,19 @@ describe("useBatchLoading", () => {
|
|
|
156
194
|
data: {},
|
|
157
195
|
},
|
|
158
196
|
},
|
|
159
|
-
};
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
160
200
|
|
|
161
201
|
const initialBatchSize = 3;
|
|
162
202
|
const riverId = "123";
|
|
163
203
|
|
|
204
|
+
const data: Partial<ZappUIComponent>[] = [
|
|
205
|
+
{ data: { source: "url1" } },
|
|
206
|
+
{ data: { source: "url2" } },
|
|
207
|
+
{ data: { source: "url3" } },
|
|
208
|
+
];
|
|
209
|
+
|
|
164
210
|
const { result } = renderHook(
|
|
165
211
|
() => useBatchLoading(data, { initialBatchSize, riverId }),
|
|
166
212
|
{ wrapper, initialProps: { store } }
|
|
@@ -170,10 +216,12 @@ describe("useBatchLoading", () => {
|
|
|
170
216
|
});
|
|
171
217
|
|
|
172
218
|
it("gallery-qb: loadPipesData should be called only once for first component in the gallery", () => {
|
|
173
|
-
const store = {
|
|
219
|
+
const store = mockStore({
|
|
174
220
|
zappPipes: {},
|
|
175
221
|
test: "true",
|
|
176
|
-
};
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
177
225
|
|
|
178
226
|
const initialBatchSize = 3;
|
|
179
227
|
const riverId = "123";
|
|
@@ -183,11 +231,11 @@ describe("useBatchLoading", () => {
|
|
|
183
231
|
component_type: "gallery-qb",
|
|
184
232
|
ui_components: [{ data: { source: "url1" } }],
|
|
185
233
|
},
|
|
186
|
-
{ data: { source: "url2" }
|
|
187
|
-
{ data: { source: "url3" }
|
|
188
|
-
{ data: { source: "url4" }
|
|
189
|
-
{ data: { source: "url5" }
|
|
190
|
-
{ data: { source: "url6" }
|
|
234
|
+
{ data: { source: "url2" } },
|
|
235
|
+
{ data: { source: "url3" } },
|
|
236
|
+
{ data: { source: "url4" } },
|
|
237
|
+
{ data: { source: "url5" } },
|
|
238
|
+
{ data: { source: "url6" } },
|
|
191
239
|
// ... more items
|
|
192
240
|
];
|
|
193
241
|
|
|
@@ -196,13 +244,13 @@ describe("useBatchLoading", () => {
|
|
|
196
244
|
initialProps: { store },
|
|
197
245
|
});
|
|
198
246
|
|
|
199
|
-
const actions =
|
|
247
|
+
const actions = store.getActions();
|
|
200
248
|
|
|
201
249
|
expect(actions).toHaveLength(1);
|
|
202
250
|
});
|
|
203
251
|
|
|
204
252
|
it("gallery-qb: initial batch ready when all initial items loaded", () => {
|
|
205
|
-
const store = {
|
|
253
|
+
const store = mockStore({
|
|
206
254
|
zappPipes: {
|
|
207
255
|
url1: {
|
|
208
256
|
loading: false,
|
|
@@ -210,19 +258,20 @@ describe("useBatchLoading", () => {
|
|
|
210
258
|
data: {},
|
|
211
259
|
},
|
|
212
260
|
},
|
|
213
|
-
};
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
214
264
|
|
|
215
265
|
const initialBatchSize = 3;
|
|
216
266
|
const riverId = "123";
|
|
217
267
|
|
|
218
|
-
const data = [
|
|
268
|
+
const data: Partial<ZappUIComponent>[] = [
|
|
219
269
|
{
|
|
220
270
|
component_type: "gallery-qb",
|
|
221
|
-
data: {},
|
|
222
|
-
ui_components: [{ data: { source: "url1" } }] as any,
|
|
271
|
+
ui_components: [{ data: { source: "url1" } }],
|
|
223
272
|
},
|
|
224
|
-
{ data: { source: "url2" }
|
|
225
|
-
{ data: { source: "url3" }
|
|
273
|
+
{ data: { source: "url2" } },
|
|
274
|
+
{ data: { source: "url3" } },
|
|
226
275
|
];
|
|
227
276
|
|
|
228
277
|
const { result } = renderHook(
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
getSearchContext,
|
|
11
11
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
import { isGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
13
|
-
import { useScreenContext } from "../screen
|
|
13
|
+
import { useScreenContext } from "../screen";
|
|
14
14
|
|
|
15
15
|
type Options = {
|
|
16
16
|
initialBatchSize?: number;
|
|
@@ -5,7 +5,7 @@ import { getDatasourceUrl } from "@applicaster/zapp-react-native-ui-components/D
|
|
|
5
5
|
import { usePipesContexts } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/usePipesContexts";
|
|
6
6
|
import { clearPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
7
7
|
|
|
8
|
-
import { useRoute } from "../navigation
|
|
8
|
+
import { useRoute } from "../navigation";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* reset river components cache when screen is unmounted
|
|
@@ -127,10 +127,10 @@ export function isNavBarVisible(
|
|
|
127
127
|
|
|
128
128
|
export const useBackHandler = (cb: () => boolean) => {
|
|
129
129
|
useEffect(() => {
|
|
130
|
-
|
|
130
|
+
BackHandler.addEventListener("hardwareBackPress", cb);
|
|
131
131
|
|
|
132
132
|
return () => {
|
|
133
|
-
|
|
133
|
+
BackHandler.removeEventListener("hardwareBackPress", cb);
|
|
134
134
|
};
|
|
135
135
|
}, [cb]);
|
|
136
136
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
|
|
1
2
|
import { useNavigation } from "./useNavigation";
|
|
2
3
|
import { usePathname } from "./usePathname";
|
|
3
4
|
|
|
@@ -6,11 +7,14 @@ export const useIsScreenActive = () => {
|
|
|
6
7
|
const pathname = usePathname();
|
|
7
8
|
const { currentRoute, videoModalState } = useNavigation();
|
|
8
9
|
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
if (videoModalState.visible) {
|
|
11
|
+
if (pathname.includes(ROUTE_TYPES.VIDEO_MODAL)) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (["FULLSCREEN", "MAXIMIZED", "PIP"].includes(videoModalState.mode)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
return pathname === currentRoute;
|
|
@@ -2,7 +2,7 @@ import { useContext, useMemo } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
|
|
4
4
|
import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
|
|
5
|
-
import { useNavigation } from "../navigation
|
|
5
|
+
import { useNavigation } from "../navigation";
|
|
6
6
|
|
|
7
7
|
import { ScreenContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
|
|
8
8
|
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import React from "react";
|
|
2
3
|
import { render, screen } from "@testing-library/react-native";
|
|
3
4
|
import { Text } from "react-native";
|
|
4
|
-
import {
|
|
5
|
+
import { useZStore, ZStoreProvider } from "../ZStoreProvider";
|
|
5
6
|
import { useStore } from "zustand";
|
|
6
7
|
|
|
7
8
|
interface TestState {
|
|
@@ -3,7 +3,7 @@ import { NativeModules, StyleSheet, View } from "react-native";
|
|
|
3
3
|
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
|
|
4
4
|
|
|
5
5
|
import { isApplePlatform, isWeb } from "../reactUtils";
|
|
6
|
-
import { useRivers } from "../reactHooks
|
|
6
|
+
import { useRivers } from "../reactHooks";
|
|
7
7
|
|
|
8
8
|
const layoutReducer = (state, { payload }) => {
|
|
9
9
|
return state.map((item, index, _state) => ({
|
package/services/js2native.ts
CHANGED
|
@@ -496,6 +496,7 @@ async function removeStorageListenerHandler(payload: { listenerId?: string }) {
|
|
|
496
496
|
function log({ level, messages }) {
|
|
497
497
|
try {
|
|
498
498
|
const parsedMessages = parseJsonIfNeeded(messages);
|
|
499
|
+
// eslint-disable-next-line no-console
|
|
499
500
|
const logFn = console[level] || console.log;
|
|
500
501
|
|
|
501
502
|
if (Array.isArray(parsedMessages)) {
|
package/testUtils/index.tsx
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import * as R from "ramda";
|
|
2
|
+
|
|
3
3
|
import React, { PropsWithChildren } from "react";
|
|
4
|
-
import configureStore from "redux-mock-store";
|
|
5
|
-
import { Provider } from "react-redux";
|
|
6
4
|
import { View } from "react-native";
|
|
7
|
-
import thunk from "redux-thunk";
|
|
8
|
-
import * as R from "ramda";
|
|
9
5
|
|
|
6
|
+
import { Provider } from "react-redux";
|
|
7
|
+
import thunk from "redux-thunk";
|
|
8
|
+
import configureStore from "redux-mock-store";
|
|
9
|
+
import { SafeAreaProvider } from "react-native-safe-area-context";
|
|
10
10
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { render } from "@testing-library/react-native";
|
|
13
13
|
import { AnalyticsProvider } from "../analyticsUtils";
|
|
14
|
+
import { ThemeContext } from "../theme";
|
|
14
15
|
|
|
15
16
|
export { getByTestId } from "./getByTestId";
|
|
16
17
|
|
package/time/BackgroundTimer.ts
CHANGED
|
@@ -13,13 +13,15 @@ class BackgroundTimer {
|
|
|
13
13
|
|
|
14
14
|
const EventEmitter = platformSelect({
|
|
15
15
|
android: DeviceEventEmitter,
|
|
16
|
-
|
|
16
|
+
android_tv: DeviceEventEmitter,
|
|
17
|
+
amazon: DeviceEventEmitter, // probably does not exist and uses android_tv
|
|
17
18
|
default: undefined,
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
EventEmitter?.addListener("BackgroundTimer.timer.fired", (id: number) => {
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const callback = this.callbacks[id];
|
|
23
|
+
|
|
24
|
+
if (callback) {
|
|
23
25
|
delete this.callbacks[id];
|
|
24
26
|
callback();
|
|
25
27
|
}
|