@applicaster/zapp-react-native-utils 14.0.0-alpha.2523527255 → 14.0.0-alpha.2893452677
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 +0 -1
- package/actionsExecutor/ScreenActions.ts +20 -19
- package/analyticsUtils/__tests__/analyticsUtils.test.js +0 -11
- package/appUtils/contextKeysManager/contextResolver.ts +29 -1
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +5 -0
- package/appUtils/focusManager/__tests__/focusManager.test.js +1 -1
- package/appUtils/focusManager/index.ios.ts +10 -0
- package/appUtils/focusManager/index.ts +82 -11
- package/appUtils/focusManagerAux/utils/index.ts +106 -3
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +0 -1
- package/package.json +2 -3
- package/reactHooks/cell-click/__tests__/index.test.js +3 -0
- package/reactHooks/debugging/__tests__/index.test.js +0 -1
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +8 -2
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +57 -37
- package/reactHooks/feed/index.ts +2 -0
- package/reactHooks/feed/useBatchLoading.ts +14 -9
- package/reactHooks/feed/useFeedLoader.tsx +39 -50
- package/reactHooks/feed/useLoadPipesDataDispatch.ts +57 -0
- package/reactHooks/navigation/useScreenStateStore.ts +3 -3
- package/reactHooks/state/index.ts +1 -1
- package/reactHooks/state/useHomeRiver.ts +4 -2
- package/screenPickerUtils/index.ts +7 -0
- package/storage/ScreenSingleValueProvider.ts +25 -22
- package/storage/ScreenStateMultiSelectProvider.ts +26 -23
- package/utils/__tests__/find.test.ts +36 -0
- package/utils/__tests__/pathOr.test.ts +37 -0
- package/utils/__tests__/startsWith.test.ts +30 -0
- package/utils/find.ts +3 -0
- package/utils/index.ts +7 -0
- package/utils/pathOr.ts +5 -0
- package/utils/startsWith.ts +9 -0
|
@@ -2,15 +2,12 @@ import { renderHook } from "@testing-library/react-hooks";
|
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import * as zappPipesModule from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
4
4
|
import * as reactReduxModules from "react-redux";
|
|
5
|
-
import { Provider } from "react-redux";
|
|
6
5
|
import * as React from "react";
|
|
7
|
-
import configureStore from "redux-mock-store";
|
|
8
|
-
import thunk from "redux-thunk";
|
|
9
6
|
import * as useRouteHook from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute";
|
|
10
7
|
import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
11
8
|
import { useFeedLoader } from "../useFeedLoader";
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
import { WrappedWithProviders } from "../../../testUtils";
|
|
10
|
+
import { ScreenStateResolver } from "../../../appUtils/contextKeysManager/contextResolver";
|
|
14
11
|
|
|
15
12
|
jest.useFakeTimers({ legacyFakeTimers: true });
|
|
16
13
|
|
|
@@ -55,13 +52,15 @@ const mockZappPipesData = {
|
|
|
55
52
|
|
|
56
53
|
describe("useFeedLoader", () => {
|
|
57
54
|
describe("with cached feed url", () => {
|
|
58
|
-
const store =
|
|
55
|
+
const store = {
|
|
59
56
|
plugins: [],
|
|
60
57
|
zappPipes: { "test://testfakeurl": mockZappPipesData },
|
|
61
|
-
}
|
|
58
|
+
};
|
|
62
59
|
|
|
63
|
-
const wrapper: React.FC<any> = ({ children }) => (
|
|
64
|
-
<
|
|
60
|
+
const wrapper: React.FC<any> = ({ children, ...props }) => (
|
|
61
|
+
<WrappedWithProviders store={props.store || store}>
|
|
62
|
+
{children}
|
|
63
|
+
</WrappedWithProviders>
|
|
65
64
|
);
|
|
66
65
|
|
|
67
66
|
it("returns cached feed", () => {
|
|
@@ -110,8 +109,10 @@ describe("useFeedLoader", () => {
|
|
|
110
109
|
describe("without cached feeds", () => {
|
|
111
110
|
const feedUrl = "test://testfakeurl2";
|
|
112
111
|
|
|
113
|
-
const wrapper: React.FC<any> = ({ children,
|
|
114
|
-
<
|
|
112
|
+
const wrapper: React.FC<any> = ({ children, ...props }) => (
|
|
113
|
+
<WrappedWithProviders store={props.store}>
|
|
114
|
+
{children}
|
|
115
|
+
</WrappedWithProviders>
|
|
115
116
|
);
|
|
116
117
|
|
|
117
118
|
it("It loads data for new url and returns it", () => {
|
|
@@ -123,10 +124,10 @@ describe("useFeedLoader", () => {
|
|
|
123
124
|
.spyOn(zappPipesModule, "loadPipesData")
|
|
124
125
|
.mockImplementation(jest.fn());
|
|
125
126
|
|
|
126
|
-
const initialStore =
|
|
127
|
+
const initialStore = {
|
|
127
128
|
plugins: [],
|
|
128
129
|
zappPipes: { "test://testfakeurl": "foobar" },
|
|
129
|
-
}
|
|
130
|
+
};
|
|
130
131
|
|
|
131
132
|
const { result, rerender } = renderHook(
|
|
132
133
|
() => useFeedLoader({ feedUrl: "test://testfakeurl2" }),
|
|
@@ -135,20 +136,19 @@ describe("useFeedLoader", () => {
|
|
|
135
136
|
|
|
136
137
|
expect(result.current.data).toBeNull();
|
|
137
138
|
|
|
138
|
-
expect(loadPipesDataSpy).
|
|
139
|
+
expect(loadPipesDataSpy).toHaveBeenCalledWith(feedUrl, {
|
|
139
140
|
clearCache: true,
|
|
140
141
|
riverId: undefined,
|
|
142
|
+
callback: expect.any(Function),
|
|
141
143
|
resolvers: {
|
|
142
|
-
screen:
|
|
143
|
-
screenStateStore: undefined,
|
|
144
|
-
},
|
|
144
|
+
screen: expect.any(ScreenStateResolver),
|
|
145
145
|
},
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
const store2 =
|
|
148
|
+
const store2 = {
|
|
149
149
|
plugins: [],
|
|
150
150
|
zappPipes: { "test://testfakeurl2": mockZappPipesData },
|
|
151
|
-
}
|
|
151
|
+
};
|
|
152
152
|
|
|
153
153
|
rerender({ store: store2 });
|
|
154
154
|
|
|
@@ -169,10 +169,10 @@ describe("useFeedLoader", () => {
|
|
|
169
169
|
.spyOn(reactReduxModules, "useDispatch")
|
|
170
170
|
.mockImplementation(() => jest.fn());
|
|
171
171
|
|
|
172
|
-
const initialStore =
|
|
172
|
+
const initialStore = {
|
|
173
173
|
plugins: [],
|
|
174
174
|
zappPipes: { "test://testfakeurl": "foobar" },
|
|
175
|
-
}
|
|
175
|
+
};
|
|
176
176
|
|
|
177
177
|
const { result, rerender } = renderHook(
|
|
178
178
|
() => useFeedLoader({ feedUrl: "test://testfakeurl2" }),
|
|
@@ -181,20 +181,22 @@ describe("useFeedLoader", () => {
|
|
|
181
181
|
|
|
182
182
|
expect(result.current.data).toBeNull();
|
|
183
183
|
|
|
184
|
-
expect(loadPipesDataSpy).
|
|
184
|
+
expect(loadPipesDataSpy.mock.calls[0][0]).toBe(feedUrl);
|
|
185
|
+
|
|
186
|
+
expect(loadPipesDataSpy.mock.calls[0][1]).toMatchObject({
|
|
185
187
|
clearCache: true,
|
|
186
188
|
riverId: undefined,
|
|
187
189
|
resolvers: {
|
|
188
190
|
screen: {
|
|
189
|
-
screenStateStore:
|
|
191
|
+
screenStateStore: expect.any(Function),
|
|
190
192
|
},
|
|
191
193
|
},
|
|
192
194
|
});
|
|
193
195
|
|
|
194
|
-
const store2 =
|
|
196
|
+
const store2 = {
|
|
195
197
|
plugins: [],
|
|
196
198
|
zappPipes: { "test://testfakeurl2": mockZappPipesData },
|
|
197
|
-
}
|
|
199
|
+
};
|
|
198
200
|
|
|
199
201
|
rerender({ store: store2 });
|
|
200
202
|
|
|
@@ -207,8 +209,10 @@ describe("useFeedLoader", () => {
|
|
|
207
209
|
const feedUrl = "test://testfakeurl";
|
|
208
210
|
const feedUrlWithNext = "test://withnexttestfakeurl";
|
|
209
211
|
|
|
210
|
-
const wrapper: React.FC<any> = ({ children,
|
|
211
|
-
<
|
|
212
|
+
const wrapper: React.FC<any> = ({ children, ...props }) => (
|
|
213
|
+
<WrappedWithProviders store={props.store || {}}>
|
|
214
|
+
{children}
|
|
215
|
+
</WrappedWithProviders>
|
|
212
216
|
);
|
|
213
217
|
|
|
214
218
|
describe("reloadData", () => {
|
|
@@ -221,10 +225,10 @@ describe("useFeedLoader", () => {
|
|
|
221
225
|
.spyOn(reactReduxModules, "useDispatch")
|
|
222
226
|
.mockImplementation(() => jest.fn());
|
|
223
227
|
|
|
224
|
-
const initialStore =
|
|
228
|
+
const initialStore = {
|
|
225
229
|
plugins: [],
|
|
226
230
|
zappPipes: { [feedUrl]: "foobar" },
|
|
227
|
-
}
|
|
231
|
+
};
|
|
228
232
|
|
|
229
233
|
const { result } = renderHook(() => useFeedLoader({ feedUrl }), {
|
|
230
234
|
wrapper,
|
|
@@ -233,14 +237,22 @@ describe("useFeedLoader", () => {
|
|
|
233
237
|
|
|
234
238
|
const { reloadData } = result.current;
|
|
235
239
|
|
|
236
|
-
reloadData();
|
|
240
|
+
reloadData?.();
|
|
241
|
+
|
|
242
|
+
expect(loadPipesDataSpy).toHaveBeenCalled();
|
|
243
|
+
|
|
244
|
+
expect(
|
|
245
|
+
loadPipesDataSpy.mock.calls[loadPipesDataSpy.mock.calls.length - 1][0]
|
|
246
|
+
).toBe(feedUrl);
|
|
237
247
|
|
|
238
|
-
expect(
|
|
248
|
+
expect(
|
|
249
|
+
loadPipesDataSpy.mock.calls[loadPipesDataSpy.mock.calls.length - 1][1]
|
|
250
|
+
).toMatchObject({
|
|
239
251
|
clearCache: true,
|
|
240
252
|
silentRefresh: true,
|
|
241
253
|
resolvers: {
|
|
242
254
|
screen: {
|
|
243
|
-
screenStateStore:
|
|
255
|
+
screenStateStore: expect.any(Function),
|
|
244
256
|
},
|
|
245
257
|
},
|
|
246
258
|
});
|
|
@@ -262,10 +274,10 @@ describe("useFeedLoader", () => {
|
|
|
262
274
|
.spyOn(reactReduxModules, "useDispatch")
|
|
263
275
|
.mockImplementation(() => jest.fn());
|
|
264
276
|
|
|
265
|
-
const initialStore =
|
|
277
|
+
const initialStore = {
|
|
266
278
|
plugins: [],
|
|
267
279
|
zappPipes: { [feedUrlWithNext]: { data: { next: nextUrl } } },
|
|
268
|
-
}
|
|
280
|
+
};
|
|
269
281
|
|
|
270
282
|
const { result } = renderHook(
|
|
271
283
|
() => useFeedLoader({ feedUrl: feedUrlWithNext }),
|
|
@@ -277,14 +289,22 @@ describe("useFeedLoader", () => {
|
|
|
277
289
|
|
|
278
290
|
const { loadNext } = result.current;
|
|
279
291
|
|
|
280
|
-
loadNext();
|
|
292
|
+
loadNext?.();
|
|
293
|
+
|
|
294
|
+
expect(loadPipesDataSpy).toHaveBeenCalled();
|
|
295
|
+
|
|
296
|
+
expect(
|
|
297
|
+
loadPipesDataSpy.mock.calls[loadPipesDataSpy.mock.calls.length - 1][0]
|
|
298
|
+
).toBe(nextUrl);
|
|
281
299
|
|
|
282
|
-
expect(
|
|
300
|
+
expect(
|
|
301
|
+
loadPipesDataSpy.mock.calls[loadPipesDataSpy.mock.calls.length - 1][1]
|
|
302
|
+
).toMatchObject({
|
|
283
303
|
parentFeed: feedUrlWithNext,
|
|
284
304
|
silentRefresh: true,
|
|
285
305
|
resolvers: {
|
|
286
306
|
screen: {
|
|
287
|
-
screenStateStore:
|
|
307
|
+
screenStateStore: expect.any(Function),
|
|
288
308
|
},
|
|
289
309
|
},
|
|
290
310
|
});
|
package/reactHooks/feed/index.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { complement, compose, isNil, map, min, prop, take, uniq } from "ramda";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import {
|
|
4
|
-
ZappPipes,
|
|
5
|
-
useAppDispatch,
|
|
6
|
-
useZappPipesFeed,
|
|
7
|
-
} from "@applicaster/zapp-react-native-redux";
|
|
3
|
+
import { useZappPipesFeed } from "@applicaster/zapp-react-native-redux";
|
|
8
4
|
import { isNilOrEmpty } from "../../reactUtils/helpers";
|
|
9
5
|
import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
10
6
|
import {
|
|
11
7
|
getInflatedDataSourceUrl,
|
|
12
8
|
getSearchContext,
|
|
9
|
+
useLoadPipesDataDispatch,
|
|
13
10
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
14
11
|
import { isGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
15
12
|
import { useScreenContext } from "../screen";
|
|
@@ -65,7 +62,6 @@ export const useBatchLoading = (
|
|
|
65
62
|
componentsToRender: { data?: ZappDataSource; component_type: string }[],
|
|
66
63
|
options: Options
|
|
67
64
|
) => {
|
|
68
|
-
const dispatch = useAppDispatch();
|
|
69
65
|
const { screen: screenContext, entry: entryContext } = useScreenContext();
|
|
70
66
|
const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
|
|
71
67
|
const [hasEverBeenReady, setHasEverBeenReady] = React.useState(false);
|
|
@@ -122,6 +118,8 @@ export const useBatchLoading = (
|
|
|
122
118
|
|
|
123
119
|
const feeds = useZappPipesFeed(feedUrls);
|
|
124
120
|
|
|
121
|
+
const loadPipesDataDispatcher = useLoadPipesDataDispatch();
|
|
122
|
+
|
|
125
123
|
// dispatch loadPipesData for each feed that is not loaded
|
|
126
124
|
const runBatchLoading = React.useCallback(() => {
|
|
127
125
|
batchComponents.forEach((rawData: any) => {
|
|
@@ -140,13 +138,20 @@ export const useBatchLoading = (
|
|
|
140
138
|
|
|
141
139
|
if (mappedFeedUrl) {
|
|
142
140
|
// 4. load data
|
|
143
|
-
return
|
|
144
|
-
|
|
141
|
+
return loadPipesDataDispatcher(
|
|
142
|
+
mappedFeedUrl,
|
|
143
|
+
{
|
|
144
|
+
riverId: options.riverId,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
withResolvers: true,
|
|
148
|
+
withScreenRouteMapping: true,
|
|
149
|
+
}
|
|
145
150
|
);
|
|
146
151
|
}
|
|
147
152
|
}
|
|
148
153
|
});
|
|
149
|
-
}, [feedUrls, feeds]);
|
|
154
|
+
}, [feedUrls, feeds, loadPipesDataDispatcher]);
|
|
150
155
|
|
|
151
156
|
React.useEffect(() => {
|
|
152
157
|
runBatchLoading();
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
ZappPipes,
|
|
5
|
-
useAppDispatch,
|
|
6
|
-
useZappPipesFeed,
|
|
7
|
-
} from "@applicaster/zapp-react-native-redux";
|
|
3
|
+
import { useZappPipesFeed } from "@applicaster/zapp-react-native-redux";
|
|
8
4
|
|
|
9
5
|
import { reactHooksLogger } from "../logger";
|
|
10
6
|
import { shouldDispatchData, useIsInitialRender } from "../utils";
|
|
11
7
|
import { useInflatedUrl } from "./useInflatedUrl";
|
|
12
|
-
import {
|
|
13
|
-
import { useScreenResolvers } from "@applicaster/zapp-react-native-utils/actionsExecutor/screenResolver";
|
|
8
|
+
import { useLoadPipesDataDispatch } from "./useLoadPipesDataDispatch";
|
|
14
9
|
|
|
15
10
|
const logger = reactHooksLogger.addSubsystem("useFeedLoader");
|
|
16
11
|
|
|
@@ -52,64 +47,62 @@ export const useFeedLoader = ({
|
|
|
52
47
|
}, []);
|
|
53
48
|
|
|
54
49
|
const isInitialRender = useIsInitialRender();
|
|
55
|
-
const dispatch = useAppDispatch();
|
|
56
|
-
const { screenData } = useRoute();
|
|
57
|
-
const resolvers = useScreenResolvers();
|
|
58
50
|
|
|
59
51
|
const callableFeedUrl = useInflatedUrl({ feedUrl, mapping });
|
|
60
52
|
|
|
61
53
|
const currentFeed = useZappPipesFeed(callableFeedUrl);
|
|
62
54
|
|
|
63
|
-
const
|
|
64
|
-
(screenData as LegacyNavigationScreenData)?.targetScreen?.id ??
|
|
65
|
-
screenData?.id;
|
|
55
|
+
const loadPipesDataDispatcher = useLoadPipesDataDispatch();
|
|
66
56
|
|
|
67
57
|
const reloadData = React.useCallback<ReloadDataFunction>(
|
|
68
58
|
(silentRefresh = true, callback) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
59
|
+
loadPipesDataDispatcher(
|
|
60
|
+
callableFeedUrl,
|
|
61
|
+
{
|
|
62
|
+
clearCache: true,
|
|
63
|
+
silentRefresh,
|
|
64
|
+
callback,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
withResolvers: true,
|
|
68
|
+
}
|
|
69
|
+
);
|
|
80
70
|
},
|
|
81
|
-
[callableFeedUrl
|
|
71
|
+
[callableFeedUrl]
|
|
82
72
|
);
|
|
83
73
|
|
|
84
74
|
const loadNext: FeedLoaderResponse["loadNext"] = React.useCallback(() => {
|
|
85
75
|
if (callableFeedUrl) {
|
|
86
76
|
const nextFeed = currentFeed?.data?.next;
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
78
|
+
loadPipesDataDispatcher(
|
|
79
|
+
nextFeed,
|
|
80
|
+
{
|
|
81
|
+
silentRefresh: true,
|
|
82
|
+
parentFeed: callableFeedUrl,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
withResolvers: true,
|
|
86
|
+
}
|
|
87
|
+
);
|
|
98
88
|
}
|
|
99
|
-
}, [callableFeedUrl, currentFeed?.data?.next
|
|
89
|
+
}, [callableFeedUrl, currentFeed?.data?.next]);
|
|
100
90
|
|
|
101
91
|
useEffect(() => {
|
|
102
92
|
if (
|
|
103
93
|
shouldDispatchData(callableFeedUrl, currentFeed, pipesOptions.clearCache)
|
|
104
94
|
) {
|
|
105
95
|
if (callableFeedUrl && !pipesOptions.skipLoading) {
|
|
106
|
-
|
|
107
|
-
|
|
96
|
+
loadPipesDataDispatcher(
|
|
97
|
+
callableFeedUrl,
|
|
98
|
+
{
|
|
108
99
|
...pipesOptions,
|
|
109
100
|
clearCache: true,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
withResolvers: true,
|
|
104
|
+
withScreenRouteMapping: true,
|
|
105
|
+
}
|
|
113
106
|
);
|
|
114
107
|
} else if (!callableFeedUrl) {
|
|
115
108
|
logger.info({
|
|
@@ -133,20 +126,16 @@ export const useFeedLoader = ({
|
|
|
133
126
|
jsOnly: true,
|
|
134
127
|
});
|
|
135
128
|
}
|
|
136
|
-
}, [
|
|
129
|
+
}, []);
|
|
137
130
|
|
|
138
131
|
// Reload feed when feedUrl changes, unless skipLoading is true
|
|
139
132
|
useEffect(() => {
|
|
140
133
|
if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
riverId,
|
|
145
|
-
resolvers,
|
|
146
|
-
})
|
|
147
|
-
);
|
|
134
|
+
loadPipesDataDispatcher(callableFeedUrl, pipesOptions, {
|
|
135
|
+
withResolvers: true,
|
|
136
|
+
});
|
|
148
137
|
}
|
|
149
|
-
}, [callableFeedUrl,
|
|
138
|
+
}, [callableFeedUrl, isInitialRender, pipesOptions.skipLoading]);
|
|
150
139
|
|
|
151
140
|
return React.useMemo(() => {
|
|
152
141
|
if (!callableFeedUrl || !feedUrl) {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useAppDispatch,
|
|
3
|
+
ZappPipes,
|
|
4
|
+
} from "@applicaster/zapp-react-native-redux";
|
|
5
|
+
import { applyScreenRouteDefaults } from "@applicaster/zapp-react-native-redux/ZappPipes/feedProcessor";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { useScreenResolvers } from "../../actionsExecutor/screenResolver";
|
|
8
|
+
import { useRoute } from "../navigation";
|
|
9
|
+
import { useScreenStateStore } from "../navigation/useScreenStateStore";
|
|
10
|
+
|
|
11
|
+
export const useLoadPipesDataDispatch = () => {
|
|
12
|
+
const screenStateStore = useScreenStateStore();
|
|
13
|
+
const resolvers = useScreenResolvers();
|
|
14
|
+
const dispatch = useAppDispatch();
|
|
15
|
+
|
|
16
|
+
const { pathname, screenData } = useRoute();
|
|
17
|
+
|
|
18
|
+
const riverId =
|
|
19
|
+
(screenData as LegacyNavigationScreenData)?.targetScreen?.id ??
|
|
20
|
+
screenData?.id;
|
|
21
|
+
|
|
22
|
+
const onLoadCB = (options) => (data, _err) => {
|
|
23
|
+
options?.callback?.();
|
|
24
|
+
|
|
25
|
+
if (data) {
|
|
26
|
+
applyScreenRouteDefaults(data, screenStateStore, pathname);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return React.useCallback(
|
|
31
|
+
(
|
|
32
|
+
url: string,
|
|
33
|
+
options = {},
|
|
34
|
+
{
|
|
35
|
+
withResolvers = false,
|
|
36
|
+
withScreenRouteMapping = false,
|
|
37
|
+
}: {
|
|
38
|
+
withResolvers?: boolean;
|
|
39
|
+
withScreenRouteMapping?: boolean;
|
|
40
|
+
} = {}
|
|
41
|
+
) => {
|
|
42
|
+
if (url) {
|
|
43
|
+
dispatch(
|
|
44
|
+
ZappPipes.loadPipesData(url, {
|
|
45
|
+
riverId,
|
|
46
|
+
resolvers: withResolvers ? resolvers : undefined,
|
|
47
|
+
...options,
|
|
48
|
+
callback: withScreenRouteMapping
|
|
49
|
+
? onLoadCB(options)
|
|
50
|
+
: options?.callback,
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
[]
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useScreenContextV2 } from "../screen/useScreenContext";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
|
|
4
4
|
export const useScreenStateStore = () => {
|
|
5
|
-
const
|
|
5
|
+
const _stateStore = useScreenContextV2()._stateStore;
|
|
6
6
|
|
|
7
|
-
return useMemo(() =>
|
|
7
|
+
return useMemo(() => _stateStore, []);
|
|
8
8
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import * as R from "ramda";
|
|
2
1
|
import { useRivers } from "./useRivers";
|
|
3
2
|
|
|
3
|
+
export const getHomeRiver = (rivers: Record<string, ZappRiver>) =>
|
|
4
|
+
Object.values(rivers).find((river: ZappRiver) => river.home);
|
|
5
|
+
|
|
4
6
|
export const useHomeRiver = () => {
|
|
5
7
|
const rivers = useRivers();
|
|
6
8
|
|
|
7
|
-
return
|
|
9
|
+
return getHomeRiver(rivers);
|
|
8
10
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const getFocusableId = (id) => `PickerItem.${id}`;
|
|
2
|
+
|
|
3
|
+
export const getPickerSelectorId = (id) => `PickerSelector.${id}`;
|
|
4
|
+
|
|
5
|
+
export const SCREEN_PICKER_CONTAINER = "ScreenPickerContainer";
|
|
6
|
+
|
|
7
|
+
export const getScreenPickerId = (id) => `${SCREEN_PICKER_CONTAINER}.${id}`;
|
|
@@ -2,6 +2,7 @@ import { BehaviorSubject } from "rxjs";
|
|
|
2
2
|
import { SingleValueProvider } from "./StorageSingleSelectProvider";
|
|
3
3
|
import { createLogger } from "../logger";
|
|
4
4
|
import { bridgeLogger } from "../../zapp-react-native-bridge/logger";
|
|
5
|
+
import { useScreenStateStore } from "../reactHooks/navigation/useScreenStateStore";
|
|
5
6
|
|
|
6
7
|
export const { log_debug, log_error } = createLogger({
|
|
7
8
|
category: "ScreenSingleValueProvider",
|
|
@@ -22,7 +23,7 @@ export class ScreenSingleValueProvider implements SingleValueProvider {
|
|
|
22
23
|
public static getProvider(
|
|
23
24
|
key: string,
|
|
24
25
|
screenRoute: string,
|
|
25
|
-
screenStateStore:
|
|
26
|
+
screenStateStore: ReturnType<typeof useScreenStateStore>
|
|
26
27
|
): SingleValueProvider {
|
|
27
28
|
if (!key) {
|
|
28
29
|
throw new Error("ScreenSingleValueProvider: Key is required");
|
|
@@ -66,7 +67,7 @@ export class ScreenSingleValueProvider implements SingleValueProvider {
|
|
|
66
67
|
private constructor(
|
|
67
68
|
private key: string,
|
|
68
69
|
route: string,
|
|
69
|
-
private screenStateStore:
|
|
70
|
+
private screenStateStore: ReturnType<typeof useScreenStateStore>
|
|
70
71
|
) {
|
|
71
72
|
if (!key) {
|
|
72
73
|
throw new Error("ScreenSingleValueProvider: Key is required");
|
|
@@ -88,7 +89,9 @@ export class ScreenSingleValueProvider implements SingleValueProvider {
|
|
|
88
89
|
log_debug("ScreenSingleValueProvider: Initializing", { key, route });
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
private updateStore(
|
|
92
|
+
private updateStore(
|
|
93
|
+
screenStateStore: ReturnType<typeof useScreenStateStore>
|
|
94
|
+
): void {
|
|
92
95
|
this.cleanup();
|
|
93
96
|
this.screenStateStore = screenStateStore;
|
|
94
97
|
this.setupScreenStateSubscription();
|
|
@@ -100,25 +103,25 @@ export class ScreenSingleValueProvider implements SingleValueProvider {
|
|
|
100
103
|
(state) => ({
|
|
101
104
|
value: state.data[this.key],
|
|
102
105
|
exists: this.key in state.data,
|
|
103
|
-
})
|
|
104
|
-
(current, previous) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
106
|
+
})
|
|
107
|
+
// (current, previous) => {
|
|
108
|
+
// if (!current.exists && previous.exists) {
|
|
109
|
+
// log_debug(
|
|
110
|
+
// `ScreenSingleValueProvider: Key deleted from store: ${this.key}`
|
|
111
|
+
// );
|
|
112
|
+
|
|
113
|
+
// // TODO: If we need to handle deletion, we can do it here
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
// if (current.value !== previous.value) {
|
|
117
|
+
// this.valueSubject.next(current.value || null);
|
|
118
|
+
|
|
119
|
+
// log_debug(`ScreenSingleValueProvider: Key updated: ${this.key}`, {
|
|
120
|
+
// previous: previous.value,
|
|
121
|
+
// current: current.value,
|
|
122
|
+
// });
|
|
123
|
+
// }
|
|
124
|
+
// }
|
|
122
125
|
);
|
|
123
126
|
|
|
124
127
|
log_debug(
|