@applicaster/quick-brick-core 15.0.0-rc.48 → 15.0.0-rc.49

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.
@@ -13,10 +13,6 @@ import {
13
13
  useGetScreenOrientation,
14
14
  } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
15
15
  import { focusManager } from "@applicaster/zapp-react-native-utils/focusManager/FocusManager";
16
- import {
17
- useContentTypes,
18
- usePickFromState,
19
- } from "@applicaster/zapp-react-native-redux/hooks";
20
16
 
21
17
  import reducer, {
22
18
  ACTIONS,
@@ -44,6 +40,7 @@ import {
44
40
  activeRiverSelector,
45
41
  homeRiverSelector,
46
42
  lastEntrySelector,
43
+ startUpHookPluginIdentifiersSelector,
47
44
  } from "./navigator/selectors";
48
45
 
49
46
  import { coreAppLogger } from "../logger";
@@ -79,6 +76,16 @@ import { Hook } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager
79
76
  import { URLSchemeContext } from "../DeepLinking/URLSchemeListener/URLSchemeContextProvider";
80
77
 
81
78
  import { loadingOverlayManager } from "../LoadingOverlay";
79
+ import {
80
+ selectAppLaunched,
81
+ useAppSelector,
82
+ useContentTypes,
83
+ usePlugins,
84
+ } from "@applicaster/zapp-react-native-redux";
85
+ import {
86
+ useLayoutVersion,
87
+ useRivers,
88
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
82
89
 
83
90
  const logger = coreAppLogger.addSubsystem("Navigator");
84
91
 
@@ -100,22 +107,11 @@ const platform = getPlatform();
100
107
  export function NavigationProvider({ children }: Props) {
101
108
  const { url: deepLinkURL } = React.useContext(URLSchemeContext);
102
109
 
103
- const {
104
- appData: { layoutVersion },
105
- rivers,
106
- plugins,
107
- pluginConfigurations,
108
- appState: { appLaunched },
109
- } = usePickFromState([
110
- "appData",
111
- "rivers",
112
- "plugins",
113
- "pluginConfigurations",
114
- "appState",
115
- "contentTypes",
116
- ]);
117
-
110
+ const appLaunched = useAppSelector(selectAppLaunched);
111
+ const layoutVersion = useLayoutVersion();
112
+ const rivers = useRivers();
118
113
  const contentTypes = useContentTypes();
114
+ const plugins = usePlugins();
119
115
 
120
116
  const [state, dispatch] = React.useReducer<
121
117
  NavigationReducer,
@@ -477,21 +473,11 @@ export function NavigationProvider({ children }: Props) {
477
473
  openLoadingOverlay();
478
474
  };
479
475
 
480
- const checkStartUpHooks = React.useMemo(() => {
481
- if (!pluginConfigurations) return false;
482
-
483
- const startUpHooksIdentifiers = R.compose(
484
- R.map((item) => item.plugin.identifier),
485
- R.filter(
486
- R.allPass([
487
- R.pathEq(["plugin", "api", "require_startup_execution"], true),
488
- R.pathEq(["plugin", "react_native"], true),
489
- R.pathEq(["plugin", "preload"], true),
490
- ])
491
- ),
492
- R.values
493
- )(pluginConfigurations);
476
+ const startUpHooksIdentifiers = useAppSelector(
477
+ startUpHookPluginIdentifiersSelector
478
+ );
494
479
 
480
+ const checkStartUpHooks = React.useMemo(() => {
495
481
  if (startUpHooksIdentifiers?.length) {
496
482
  const startUpHooks = R.filter(
497
483
  (plugin) => R.includes(plugin.identifier, startUpHooksIdentifiers),
@@ -523,7 +509,7 @@ export function NavigationProvider({ children }: Props) {
523
509
  }
524
510
 
525
511
  return false;
526
- }, [pluginConfigurations, plugins, rivers]);
512
+ }, [startUpHooksIdentifiers, plugins, rivers]);
527
513
 
528
514
  const [startUpHooks, _setStartUpHooks] = React.useState(checkStartUpHooks);
529
515
  const currentStartUpHooks = React.useRef(checkStartUpHooks);
@@ -726,7 +712,7 @@ export function NavigationProvider({ children }: Props) {
726
712
  activeRiver,
727
713
  getPathname: () => pathnameRef.current, // hack use to fix issue causing broken navigation as currentRoute is unreliable
728
714
  currentRoute: pathname, // TODO: remove. Current route shouldn't be needed
729
- previousAction: lastEntrySelector(state)
715
+ previousAction: (lastEntrySelector(state) as any)
730
716
  ?.action as QuickBrickNavigationActionType,
731
717
  push: pushItem,
732
718
  replace: replaceItem,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
3
 
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
+ import { usePlugins } from "@applicaster/zapp-react-native-redux";
5
5
 
6
6
  enum ReactHooks {
7
7
  useEffect = "useEffect",
@@ -39,7 +39,7 @@ function invokeScreenHook(hooksWrappers) {
39
39
  }
40
40
 
41
41
  export function usePluginScreenHooks(pathname: string) {
42
- const { plugins } = usePickFromState(["plugins"]);
42
+ const plugins = usePlugins();
43
43
 
44
44
  const hooks = React.useMemo(
45
45
  () => R.filter(hasScreenHook, plugins) || [],
@@ -1,13 +1,16 @@
1
1
  import React from "react";
2
2
  import { View } from "react-native";
3
- import { act, create } from "react-test-renderer";
4
- import { createStore } from "redux";
5
- import { Provider } from "react-redux";
6
3
 
7
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
+ import { NavigationProvider } from "../NavigationProvider";
6
+
8
7
  import { getByTestId } from "@applicaster/zapp-react-native-utils/testUtils/getByTestId";
9
- // @TODO @szhigunov to complete the migration to @testing-library/react-native
10
- // import { act, waitFor } from "@testing-library/react-native";
8
+ import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
9
+ import { act } from "@testing-library/react-native";
10
+
11
+ jest.useFakeTimers({
12
+ legacyFakeTimers: true,
13
+ });
11
14
 
12
15
  const rivers = {
13
16
  A1234: {
@@ -27,20 +30,20 @@ const rivers = {
27
30
  ui_components: [],
28
31
  hooks: {
29
32
  postload_plugins: [],
30
- preload_plugins: [
31
- {
32
- screen_id: "hook_screen",
33
- identifier: "test-hook",
34
- type: "general",
35
- weight: 7,
36
- },
37
- {
38
- screen_id: "hook_screen2",
39
- identifier: "test-hook2",
40
- type: "general",
41
- weight: 7,
42
- },
43
- ],
33
+ // preload_plugins: [
34
+ // {
35
+ // screen_id: "hook_screen",
36
+ // identifier: "test-hook",
37
+ // type: "general",
38
+ // weight: 7,
39
+ // },
40
+ // {
41
+ // screen_id: "hook_screen2",
42
+ // identifier: "test-hook2",
43
+ // type: "general",
44
+ // weight: 7,
45
+ // },
46
+ // ],
44
47
  },
45
48
  },
46
49
  D6543: {
@@ -81,13 +84,9 @@ const rivers = {
81
84
  },
82
85
  };
83
86
 
84
- jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
85
- usePickFromState: jest.fn(() => ({
86
- appData: { layoutVersion: "v2" },
87
- rivers,
88
- plugins: [],
89
- appState: { appLaunched: true },
90
- })),
87
+ jest.mock("@applicaster/zapp-react-native-redux", () => ({
88
+ ...jest.requireActual("@applicaster/zapp-react-native-redux"),
89
+ usePickFromState: jest.fn(() => ({})),
91
90
  useContentTypes: jest.fn(() => ({})),
92
91
  }));
93
92
 
@@ -107,8 +106,6 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => ({
107
106
  })),
108
107
  }));
109
108
 
110
- const { NavigationProvider } = require("../NavigationProvider");
111
-
112
109
  // eslint-disable-next-line react/prop-types
113
110
  const HookComponent = ({ callback, payload }: Props) => {
114
111
  if (payload?.id === "D6543") {
@@ -154,18 +151,13 @@ const failingHook = {
154
151
  name: "failing hook",
155
152
  };
156
153
 
157
- // const store = {
158
- // rivers,
159
- // plugins: [hookPlugin, hookPlugin2, failingHook],
160
- // };
161
-
162
- const store = createStore(() => ({
154
+ const store = {
163
155
  appData: { layoutVersion: "v1" },
164
- contentTypes: null,
156
+ contentTypes: {},
165
157
  rivers,
166
158
  plugins: [hookPlugin, hookPlugin2, failingHook],
167
159
  appState: { appLaunched: true },
168
- }));
160
+ };
169
161
 
170
162
  const ContextConsumer = () => {
171
163
  const { state, ...navigator } = useNavigation();
@@ -173,6 +165,7 @@ const ContextConsumer = () => {
173
165
  let renderHook;
174
166
 
175
167
  if (navigator.currentRoute.includes("/hooks/")) {
168
+ // @ts-ignore
176
169
  const { hookPlugin, payload, callback } = navigator.screenData;
177
170
  const Component = hookPlugin.module.Component;
178
171
 
@@ -192,18 +185,21 @@ const ContextConsumer = () => {
192
185
 
193
186
  const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {});
194
187
 
195
- // const renderContextConsumer = (_store = store) => {
196
- // return renderWithProviders(<ContextConsumer />, _store);
197
- // };
198
-
199
- const renderContextConsumer = (_store = store) => {
200
- return create(
201
- <Provider store={store}>
202
- <NavigationProvider>
203
- <ContextConsumer />
204
- </NavigationProvider>
205
- </Provider>
188
+ const renderContextConsumer = (_store = store) =>
189
+ renderWithProviders(
190
+ <NavigationProvider>
191
+ <ContextConsumer />
192
+ </NavigationProvider>,
193
+ _store
206
194
  );
195
+
196
+ const getNavigatorValues = (wrapper) => {
197
+ const view = getByTestId(wrapper, "WrapperView");
198
+ const navigator = view.props.navigator;
199
+
200
+ const state = view.props.state;
201
+
202
+ return { navigator, state };
207
203
  };
208
204
 
209
205
  afterAll(() => {
@@ -213,14 +209,12 @@ afterAll(() => {
213
209
  describe("<NavigationProvider />", () => {
214
210
  let wrapper;
215
211
 
216
- it("navigator contains expected properties", () => {
217
- act(() => {
218
- wrapper = renderContextConsumer();
219
- });
220
-
221
- const view = getByTestId(wrapper, "WrapperView");
212
+ beforeEach(() => {
213
+ wrapper = renderContextConsumer();
214
+ });
222
215
 
223
- const { navigator } = view.props;
216
+ it("navigator contains expected properties", () => {
217
+ const { navigator } = getNavigatorValues(wrapper);
224
218
  expect(navigator.activeRiver).toEqual(rivers.B4567);
225
219
  expect(navigator.currentRoute).toEqual("/river/B4567");
226
220
  expect(navigator.previousAction).toEqual("REPLACE");
@@ -236,148 +230,131 @@ describe("<NavigationProvider />", () => {
236
230
  });
237
231
  });
238
232
 
239
- describe("pushing a new route", () => {
233
+ it("pushing a new route sets the data to that route", async () => {
240
234
  act(() => {
241
- wrapper = renderContextConsumer();
235
+ getNavigatorValues(wrapper).navigator.push(rivers.A1234);
242
236
  });
243
237
 
244
- it("sets the data to that route", async () => {
245
- const view = getByTestId(wrapper, "WrapperView");
238
+ const { navigator, state } = getNavigatorValues(wrapper);
246
239
 
247
- act(() => view.props.navigator.push(rivers.A1234));
240
+ expect(navigator).toHaveProperty("activeRiver", rivers.A1234);
248
241
 
249
- expect(view.props.navigator).toHaveProperty("activeRiver", rivers.A1234);
242
+ expect(navigator).toHaveProperty(
243
+ "currentRoute",
244
+ "/river/B4567/river/A1234"
245
+ );
250
246
 
251
- expect(view.props.navigator).toHaveProperty(
252
- "currentRoute",
253
- "/river/B4567/river/A1234"
254
- );
255
-
256
- expect(view.props.navigator.screenData).toEqual({
257
- ...rivers.A1234,
258
- targetScreen: rivers.A1234,
259
- });
260
-
261
- expect(view.props.state.stack.mainStack).toHaveLength(2);
247
+ expect(navigator.screenData).toEqual({
248
+ ...rivers.A1234,
249
+ targetScreen: rivers.A1234,
262
250
  });
251
+
252
+ expect(state.stack.mainStack).toHaveLength(2);
263
253
  });
264
254
 
265
255
  describe("replacing a current route", () => {
266
- act(() => {
267
- wrapper = renderContextConsumer();
268
- });
269
-
270
- const view = getByTestId(wrapper, "WrapperView");
271
-
272
256
  it("sets the data to that route", () => {
273
- act(() => view.props.navigator.replace(rivers.A1234));
274
- expect(view.props.navigator).toHaveProperty("activeRiver", rivers.A1234);
257
+ act(() => getNavigatorValues(wrapper).navigator.replace(rivers.A1234));
258
+ const { navigator, state } = getNavigatorValues(wrapper);
259
+ expect(navigator).toHaveProperty("activeRiver", rivers.A1234);
275
260
 
276
- expect(view.props.navigator).toHaveProperty(
277
- "currentRoute",
278
- "/river/A1234"
279
- );
261
+ expect(navigator).toHaveProperty("currentRoute", "/river/A1234");
280
262
 
281
- expect(view.props.navigator.screenData).toEqual({
263
+ expect(navigator.screenData).toEqual({
282
264
  ...rivers.A1234,
283
265
  targetScreen: rivers.A1234,
284
266
  });
285
267
 
286
- expect(view.props.state.stack.mainStack).toHaveLength(1);
268
+ expect(state.stack.mainStack).toHaveLength(1);
287
269
  });
288
270
  });
289
271
 
290
272
  describe("going back", () => {
291
273
  describe("when there is no previous route", () => {
292
- act(() => {
293
- wrapper = renderContextConsumer();
294
- });
295
-
296
- const view = getByTestId(wrapper, "WrapperView");
297
-
298
274
  it("returns false when calling canGoBack", () => {
299
275
  let result;
300
276
 
301
277
  act(() => {
302
- result = view.props.navigator.canGoBack();
278
+ result = getNavigatorValues(wrapper).navigator.canGoBack();
303
279
  });
304
280
 
305
281
  expect(result).toBe(false);
306
282
  });
307
283
 
308
284
  it("stays on the current route", () => {
309
- act(() => view.props.navigator.goBack());
285
+ act(() => getNavigatorValues(wrapper).navigator.goBack());
286
+ const { navigator, state } = getNavigatorValues(wrapper);
310
287
 
311
- expect(view.props.navigator).toHaveProperty(
312
- "activeRiver",
313
- rivers.B4567
314
- );
288
+ expect(navigator).toHaveProperty("activeRiver", rivers.B4567);
315
289
 
316
- expect(view.props.navigator).toHaveProperty(
317
- "currentRoute",
318
- "/river/B4567"
319
- );
290
+ expect(navigator).toHaveProperty("currentRoute", "/river/B4567");
320
291
 
321
- expect(view.props.navigator.screenData).toEqual({
292
+ expect(navigator.screenData).toEqual({
322
293
  ...rivers.B4567,
323
294
  targetScreen: rivers.B4567,
324
295
  });
325
296
 
326
- expect(view.props.state.stack.mainStack).toHaveLength(1);
297
+ expect(state.stack.mainStack).toHaveLength(1);
327
298
  });
328
299
  });
329
300
 
330
301
  describe("when there is one route and we're going in a hook", () => {
331
- act(() => {
332
- wrapper = renderContextConsumer();
302
+ beforeEach(() => {
303
+ getNavigatorValues(wrapper).navigator.replace(rivers.A1234);
333
304
  });
334
305
 
335
- const view = getByTestId(wrapper, "WrapperView");
336
- act(() => view.props.navigator.replace(rivers.A1234));
306
+ it.skip("returns true when calling goBack()", () => {
307
+ wrapper = renderContextConsumer();
308
+
309
+ act(() => {
310
+ getNavigatorValues(wrapper).navigator.replace(rivers.A1234);
311
+ getNavigatorValues(wrapper).navigator.push(rivers.C0987);
312
+ });
337
313
 
338
- it("returns true when calling goBack()", () => {
339
- act(() => view.props.navigator.push(rivers.C0987));
340
- expect(view.props.state.stack.mainStack.length).toBeGreaterThan(1);
341
- expect(view.props.navigator.canGoBack()).toEqual(true);
314
+ const { navigator, state } = getNavigatorValues(wrapper);
315
+
316
+ expect(state.stack.mainStack.length).toBeGreaterThan(1);
317
+ expect(navigator.canGoBack()).toEqual(true);
342
318
  });
343
319
 
344
320
  // this test is skipped as it doesn't work on this version of react
345
321
  // where we can't properly test async actions within components
346
322
  it.skip("returns to the previous route when the hook is cancelled", () => {
347
- act(() => view.props.navigator.replace(rivers.A1234));
348
- act(() => view.props.navigator.push(rivers.D6543));
323
+ wrapper = renderContextConsumer();
349
324
 
350
- expect(view.props.navigator).toHaveProperty(
351
- "activeRiver",
352
- rivers.A1234
353
- );
325
+ act(() => {
326
+ getNavigatorValues(wrapper).navigator.replace(rivers.A1234);
327
+ getNavigatorValues(wrapper).navigator.push(rivers.D6543);
328
+ });
354
329
 
355
- expect(view.props.navigator).toHaveProperty(
356
- "currentRoute",
357
- "/river/A1234"
358
- );
330
+ const { navigator, state } = getNavigatorValues(wrapper);
359
331
 
360
- expect(view.props.navigator.screenData).toEqual(rivers.A1234);
361
- expect(view.props.state.stack.mainStack).toHaveLength(1);
332
+ expect(navigator).toHaveProperty("activeRiver", rivers.A1234);
333
+
334
+ expect(navigator).toHaveProperty("currentRoute", "/river/A1234");
335
+
336
+ expect(navigator.screenData).toEqual(rivers.A1234);
337
+ expect(state.stack.mainStack).toHaveLength(1);
362
338
  });
363
339
  });
364
340
 
365
341
  describe("when there is a previous route", () => {
366
- act(() => {
367
- wrapper = renderContextConsumer();
342
+ beforeEach(() => {
343
+ act(() => getNavigatorValues(wrapper).navigator.push(rivers.A1234));
344
+
345
+ act(() =>
346
+ getNavigatorValues(wrapper).navigator.push({
347
+ ...rivers.B4567,
348
+ id: "B4567-1",
349
+ })
350
+ );
368
351
  });
369
352
 
370
- const view = getByTestId(wrapper, "WrapperView");
371
-
372
- act(() => view.props.navigator.push(rivers.A1234));
373
-
374
- act(() => view.props.navigator.push({ ...rivers.B4567, id: "B4567-1" }));
375
-
376
353
  it("returns true when calling canGoBack", () => {
377
354
  let result;
378
355
 
379
356
  act(() => {
380
- result = view.props.navigator.canGoBack();
357
+ result = getNavigatorValues(wrapper).navigator.canGoBack();
381
358
  });
382
359
 
383
360
  expect(result).toBeTruthy();
@@ -387,74 +364,86 @@ describe("<NavigationProvider />", () => {
387
364
  let result;
388
365
 
389
366
  act(() => {
390
- result = view.props.navigator.canGoBack(false, "B4567-1");
367
+ result = getNavigatorValues(wrapper).navigator.canGoBack(
368
+ false,
369
+ "B4567-1"
370
+ );
391
371
  });
392
372
 
393
373
  expect(result).toBeTruthy();
394
374
 
395
375
  act(() => {
396
- result = view.props.navigator.canGoBack(false, "A1234");
376
+ result = getNavigatorValues(wrapper).navigator.canGoBack(
377
+ false,
378
+ "A1234"
379
+ );
397
380
  });
398
381
 
399
382
  expect(result).toBeTruthy();
400
383
  });
401
384
 
402
385
  it("returns to the previous route", () => {
403
- expect(view.props.state.stack.mainStack).toHaveLength(3);
386
+ expect(getNavigatorValues(wrapper).state.stack.mainStack).toHaveLength(
387
+ 3
388
+ );
404
389
 
405
- act(() => view.props.navigator.goBack());
390
+ act(() => getNavigatorValues(wrapper).navigator.goBack());
406
391
 
407
- expect(view.props.navigator).toHaveProperty(
392
+ expect(getNavigatorValues(wrapper).navigator).toHaveProperty(
408
393
  "activeRiver",
409
394
  rivers.A1234
410
395
  );
411
396
 
412
- expect(view.props.navigator).toHaveProperty(
397
+ expect(getNavigatorValues(wrapper).navigator).toHaveProperty(
413
398
  "currentRoute",
414
399
  "/river/B4567/river/A1234"
415
400
  );
416
401
 
417
- expect(view.props.navigator.screenData).toEqual({
402
+ expect(getNavigatorValues(wrapper).navigator.screenData).toEqual({
418
403
  ...rivers.A1234,
419
404
  targetScreen: rivers.A1234,
420
405
  });
421
406
 
422
- expect(view.props.state.stack.mainStack).toHaveLength(2);
407
+ expect(getNavigatorValues(wrapper).state.stack.mainStack).toHaveLength(
408
+ 2
409
+ );
423
410
  });
424
411
  });
425
412
 
426
413
  describe("when there is a previous route and there are hooks", () => {
427
- act(() => {
414
+ beforeEach(() => {
428
415
  wrapper = renderContextConsumer();
416
+ act(() => getNavigatorValues(wrapper).navigator.push(rivers.A1234));
417
+ act(() => getNavigatorValues(wrapper).navigator.push(rivers.C0987));
429
418
  });
430
419
 
431
- const view = getByTestId(wrapper, "WrapperView");
432
- act(() => view.props.navigator.push(rivers.A1234));
433
- act(() => view.props.navigator.push(rivers.C0987));
434
-
435
420
  it("returns to the previous entry in the stack which is not a hook", () => {
436
- expect(view.props.state.stack.mainStack).toHaveLength(3);
421
+ expect(getNavigatorValues(wrapper).state.stack.mainStack).toHaveLength(
422
+ 3
423
+ );
437
424
 
438
- expect(view.props.navigator).toHaveProperty(
425
+ expect(getNavigatorValues(wrapper).navigator).toHaveProperty(
439
426
  "currentRoute",
440
427
  "/river/B4567/river/A1234/river/C0987"
441
428
  );
442
429
 
443
- expect(view.props.navigator.screenData).toMatchObject({
430
+ expect(getNavigatorValues(wrapper).navigator.screenData).toMatchObject({
444
431
  ...rivers.C0987,
445
432
  targetScreen: rivers.C0987,
446
433
  });
447
434
 
448
- act(() => view.props.navigator.goBack());
435
+ act(() => getNavigatorValues(wrapper).navigator.goBack());
449
436
 
450
- expect(view.props.state.stack.mainStack).toHaveLength(2);
437
+ expect(getNavigatorValues(wrapper).state.stack.mainStack).toHaveLength(
438
+ 2
439
+ );
451
440
 
452
- expect(view.props.navigator).toHaveProperty(
441
+ expect(getNavigatorValues(wrapper).navigator).toHaveProperty(
453
442
  "currentRoute",
454
443
  "/river/B4567/river/A1234"
455
444
  );
456
445
 
457
- expect(view.props.navigator.screenData).toMatchObject({
446
+ expect(getNavigatorValues(wrapper).navigator.screenData).toMatchObject({
458
447
  ...rivers.A1234,
459
448
  targetScreen: rivers.A1234,
460
449
  });
@@ -2,6 +2,7 @@ import * as R from "ramda";
2
2
  import { createSelector } from "@reduxjs/toolkit";
3
3
 
4
4
  import { getPathAttributes } from "@applicaster/zapp-react-native-utils/navigationUtils";
5
+ import { selectPluginConfigurations } from "@applicaster/zapp-react-native-redux";
5
6
 
6
7
  const riverSelector = R.prop("rivers");
7
8
  const pathnameSelector = R.prop("pathname");
@@ -56,11 +57,25 @@ export const previousStackEntriesSelector = createSelector(
56
57
  )
57
58
  );
58
59
 
59
- export const lastEntrySelector = createSelector<
60
- unknown,
61
- unknown,
62
- NavigationScreenState
63
- >(
60
+ export const lastEntrySelector = createSelector(
64
61
  navigationStackSelector,
65
62
  R.compose(R.last, R.when(R.has("mainStack"), R.prop("mainStack")))
63
+ ) as (state: any) => any; // TODO: tighten type to NavigationScreenState
64
+
65
+ // Selector extracting identifiers of plugins requiring startup execution
66
+ export const startUpHookPluginIdentifiersSelector = createSelector(
67
+ selectPluginConfigurations,
68
+ (pluginConfigurations) => {
69
+ if (!pluginConfigurations) return [];
70
+
71
+ return Object.values(pluginConfigurations)
72
+ .filter(
73
+ (item) =>
74
+ "require_startup_execution" in item.plugin.api &&
75
+ item?.plugin?.api?.require_startup_execution === true &&
76
+ item?.plugin?.react_native === true &&
77
+ item?.plugin?.preload === true
78
+ )
79
+ .map((item: any) => item.plugin.identifier);
80
+ }
66
81
  );
@@ -3,7 +3,7 @@ import { Platform } from "react-native";
3
3
  import NetInfo, { NetInfoState } from "@react-native-community/netinfo";
4
4
 
5
5
  import { NetworkStatusContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NetworkStatusContext";
6
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import { usePlugins } from "@applicaster/zapp-react-native-redux";
7
7
  import {
8
8
  callAllWith,
9
9
  getNetworkHooks,
@@ -29,7 +29,7 @@ export const NetworkStatusProvider = ({
29
29
  }: {
30
30
  children: React.ReactNode;
31
31
  }) => {
32
- const { plugins } = usePickFromState("plugins");
32
+ const plugins = usePlugins();
33
33
  const [deviceStatus, setDeviceStatus] = React.useState(null);
34
34
  const currentNetInfo = NetInfo.useNetInfo();
35
35