@applicaster/quick-brick-core 12.0.0-alpha.5035843303 → 12.0.0-alpha.5050333009

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.
@@ -88,10 +88,10 @@ const getActionInitialStateSetters = (key) => {
88
88
  return R.compose(
89
89
  R.map((subscription: { [x: string]: any; pluginId: any }) => {
90
90
  return async () => {
91
+ const now = performance.now();
92
+
91
93
  logger.info({
92
- message: `Invocation Started - action plugin ${key}, pluginId: ${
93
- subscription.pluginId
94
- }: ${performance.now()}`,
94
+ message: `Invocation Started - action plugin ${key}, pluginId: ${subscription.pluginId}`,
95
95
  });
96
96
 
97
97
  const promiseFunc = subscription[key];
@@ -101,7 +101,7 @@ const getActionInitialStateSetters = (key) => {
101
101
  logger.info({
102
102
  message: `Invocation Completed - action plugin ${key}, pluginId: ${
103
103
  subscription.pluginId
104
- }: ${performance.now()}`,
104
+ }: ${performance.now() - now} ms`,
105
105
  });
106
106
 
107
107
  return result;
@@ -323,7 +323,7 @@ describe("asset cache", () => {
323
323
 
324
324
  expect(saveCacheData).toHaveBeenCalledWith(
325
325
  layoutId,
326
- newFiles.filter(({ url }) => !url.includes("fail")),
326
+ newFiles.filter(({ url }) => !url.includes("fail"))
327
327
  );
328
328
  });
329
329
 
@@ -1,6 +1,6 @@
1
1
  /// <reference types="../../" />
2
2
  import * as R from "ramda";
3
- import { log_debug, log_warning } from "./logger";
3
+ import { log_debug, log_verbose, log_warning } from "./logger";
4
4
  import { CacheManager } from "./CacheManager";
5
5
 
6
6
  import {
@@ -84,6 +84,8 @@ export async function cacheAssets({
84
84
  };
85
85
  }
86
86
 
87
+ const time = performance.now();
88
+
87
89
  try {
88
90
  const { assetFiles, cellAssets, pluginAssets, layoutAssets } =
89
91
  await getLayoutAssets({
@@ -141,18 +143,25 @@ export async function cacheAssets({
141
143
 
142
144
  newCacheState.forEach(({ file, url }) => (urlFileMap[url] = file));
143
145
 
144
- const updatedLayout = remapAssetPath(layoutAssets, layout, urlFileMap);
146
+ const updatedLayout = remapAssetPath(
147
+ layoutAssets,
148
+ layout,
149
+ urlFileMap,
150
+ "layoutAssets"
151
+ );
145
152
 
146
153
  const updatedPluginConfigurations = remapAssetPath(
147
154
  pluginAssets,
148
155
  pluginConfigurations,
149
- urlFileMap
156
+ urlFileMap,
157
+ "pluginAssets"
150
158
  );
151
159
 
152
160
  const updatedCellStyles = remapAssetPath(
153
161
  cellAssets,
154
162
  cellStyles,
155
- urlFileMap
163
+ urlFileMap,
164
+ "cellStyles"
156
165
  );
157
166
 
158
167
  return {
@@ -164,5 +173,9 @@ export async function cacheAssets({
164
173
  log_warning(`cacheAssets: Error caching assets, message: ${error.message}`);
165
174
 
166
175
  return { layout, pluginConfigurations, cellStyles };
176
+ } finally {
177
+ log_verbose(
178
+ `cacheAssets: caching assets took ${performance.now() - time} ms`
179
+ );
167
180
  }
168
181
  }
@@ -1,7 +1,4 @@
1
- import {
2
- useActions,
3
- usePickFromState,
4
- } from "@applicaster/zapp-react-native-redux/hooks";
1
+ import { useActions } from "@applicaster/zapp-react-native-redux/hooks";
5
2
  import * as R from "ramda";
6
3
  import * as React from "react";
7
4
  import axios from "axios";
@@ -28,6 +25,7 @@ import {
28
25
  } from "../../helpers";
29
26
 
30
27
  import { log_error, log_info } from "../../logger";
28
+ import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks/state";
31
29
 
32
30
  const getFeed = (query) => ({
33
31
  content: { src: query.data_source },
@@ -60,7 +58,7 @@ export function usePresentSchemeHandler({
60
58
  feedUrl: data_source,
61
59
  });
62
60
 
63
- const { rivers } = usePickFromState(["rivers"]);
61
+ const rivers = useRivers();
64
62
  const screenRiver = findRiver({ screen_id, rivers });
65
63
  const dispatch = useDispatch();
66
64
 
@@ -1,7 +1,5 @@
1
1
  import React from "react";
2
- import { render, waitFor, cleanup } from "@testing-library/react-native";
3
-
4
- jest.mock("react-native");
2
+ import { cleanup, render, waitFor } from "@testing-library/react-native";
5
3
 
6
4
  const theme = {
7
5
  screen_margin_top: 0,
@@ -10,6 +8,8 @@ const theme = {
10
8
 
11
9
  const plugins = [];
12
10
 
11
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
12
+
13
13
  jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
14
14
  useTheme: jest.fn(() => theme),
15
15
  }));
@@ -7,8 +7,6 @@ import { URLSchemeListener } from "../index";
7
7
 
8
8
  const URL = "url";
9
9
 
10
- jest.mock("react-native");
11
-
12
10
  const TestComponent = () => (
13
11
  <View>
14
12
  <Text>I'm a test component</Text>
@@ -13,6 +13,7 @@ import {
13
13
  useNavigation,
14
14
  } from "@applicaster/zapp-react-native-utils/reactHooks";
15
15
  import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
16
+ import { ModalComponent } from "@applicaster/zapp-react-native-ui-components/Components";
16
17
 
17
18
  const styles = StyleSheet.create({
18
19
  container: {
@@ -55,7 +56,10 @@ export function ModalBottomSheet(props: Props) {
55
56
  modal_bottom_sheet_tablet_max_width: sheetTabletMaxWidth,
56
57
  } = theme;
57
58
 
58
- const { ModalBottomSheetContent, modalBottomSheetContentProps } = props;
59
+ const {
60
+ ModalBottomSheetContent = ModalComponent,
61
+ modalBottomSheetContentProps,
62
+ } = props;
59
63
 
60
64
  const onLayout = useCallback(({ nativeEvent }) => {
61
65
  const calculatedHeight = nativeEvent?.layout?.height;
@@ -17,7 +17,7 @@ const styles = StyleSheet.create({
17
17
  export function ModalContent(props: Props) {
18
18
  const { modalScreenProps } = props;
19
19
 
20
- if (modalScreenProps?.screenData?.ModalBottomSheetContent) {
20
+ if (modalScreenProps?.screenData?.modalBottomSheetContentProps) {
21
21
  const { ModalBottomSheetContent, modalBottomSheetContentProps } =
22
22
  modalScreenProps?.screenData || {};
23
23
 
@@ -1,16 +1,16 @@
1
1
  import * as React from "react";
2
2
 
3
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
-
5
3
  import { ModalPresenter } from "./ModalPresenter";
6
4
  import { ModalContent } from "./ModalContent";
7
5
  import { ModalChildrenWrapper } from "./ModalChildrenWrapper";
8
6
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
9
7
  import { ScreenContextProvider } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
10
8
  import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
9
+ import { useModalStore } from "@applicaster/zapp-react-native-utils/modalState";
11
10
 
12
11
  export function ModalProvider() {
13
- const { modalState } = useNavigation();
12
+ const { modalState } = useModalStore();
13
+
14
14
  const [modalVisible, setModalVisible] = React.useState(false);
15
15
  const [modalShown, setModalShown] = React.useState(false);
16
16
 
@@ -63,6 +63,10 @@ import { findParent } from "@applicaster/zapp-react-native-ui-components/Context
63
63
  import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
64
64
  import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
65
65
  import { inflateUrl } from "@applicaster/zapp-react-native-ui-components/Components/LinkHandler/LinkHandler";
66
+ import { useModalStore } from "@applicaster/zapp-react-native-utils/modalState";
67
+ import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
68
+ import { QBUIComponentEvents } from "@applicaster/zapp-react-native-ui-components/events";
69
+ import { Hook } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager/Hook";
66
70
 
67
71
  const logger = coreAppLogger.addSubsystem("Navigator");
68
72
 
@@ -72,17 +76,6 @@ type Props = {
72
76
  plugins?: QuickBrickPlugin[];
73
77
  };
74
78
 
75
- type EntryWithParent = ZappEntry & { parent?: EntryWithParent };
76
-
77
- type SingleEntry = {
78
- data: EntryWithParent;
79
- route: string;
80
- id: string;
81
- parentId?: string;
82
- };
83
-
84
- type EntryContextType = { [K in string]: SingleEntry };
85
-
86
79
  const navigationActions = {
87
80
  [ACTIONS.PUSH]: push,
88
81
  [ACTIONS.REPLACE]: replace,
@@ -92,13 +85,6 @@ const navigationActions = {
92
85
 
93
86
  const platform = getPlatform();
94
87
 
95
- const initialModalState = {
96
- visible: false,
97
- screen: null,
98
- options: {},
99
- props: {},
100
- };
101
-
102
88
  export function NavigationProvider({ children }: Props) {
103
89
  const {
104
90
  appData: { layoutVersion },
@@ -126,17 +112,18 @@ export function NavigationProvider({ children }: Props) {
126
112
  const pathname = state?.location?.pathname;
127
113
  const pathnameRef = React.useRef(pathname);
128
114
 
129
- const { context }: EntryContextType = React.useContext(
130
- ZappPipesEntryContext.Context
131
- );
115
+ const { context } = React.useContext(ZappPipesEntryContext.Context);
132
116
 
133
- const [modalState, setModalState] =
134
- React.useState<ModalState>(initialModalState);
117
+ const { openModal, dismissModal } = useModalStore();
135
118
 
136
119
  const playNextOverlayState = React.useRef();
137
120
 
138
121
  const online = useConnectionInfo(true);
139
122
 
123
+ const replaceEvent = useSubscriberFor(
124
+ QBUIComponentEvents.navigatorReplaceItem
125
+ );
126
+
140
127
  React.useEffect(() => {
141
128
  stateRef.current = state;
142
129
  pathnameRef.current = pathname;
@@ -153,6 +140,12 @@ export function NavigationProvider({ children }: Props) {
153
140
  [pathname, rivers]
154
141
  );
155
142
 
143
+ const getModalState: () => ModalState = () => {
144
+ const { modalState } = useModalStore.getState();
145
+
146
+ return modalState;
147
+ };
148
+
156
149
  const homeRiver = React.useMemo(
157
150
  () => homeRiverSelector({ rivers }),
158
151
  [rivers]
@@ -168,7 +161,7 @@ export function NavigationProvider({ children }: Props) {
168
161
  [rivers, homeRiver]
169
162
  );
170
163
 
171
- const getStack = () => [...stateRef?.current?.stack?.mainStack];
164
+ const getStack = () => [...state?.stack?.mainStack];
172
165
 
173
166
  const openVideoModal = (
174
167
  item: ZappEntry,
@@ -260,6 +253,7 @@ export function NavigationProvider({ children }: Props) {
260
253
  item?.id !==
261
254
  legacyScreenData(state?.location?.state as NavigationScreenData)?.id
262
255
  ) {
256
+ replaceEvent();
263
257
  navigateTo(item, ACTIONS.REPLACE, options);
264
258
  }
265
259
  };
@@ -276,7 +270,7 @@ export function NavigationProvider({ children }: Props) {
276
270
  route.includes(pathname)
277
271
  );
278
272
 
279
- return pathnameStackIndex > 1;
273
+ return pathnameStackIndex >= 1;
280
274
  }
281
275
 
282
276
  if (!Number.isNaN(filteredStack?.length)) {
@@ -374,7 +368,18 @@ export function NavigationProvider({ children }: Props) {
374
368
  }
375
369
  };
376
370
 
377
- const handleHookPresent = ({ hookPlugin, route, payload }, dispose) => {
371
+ const handleHookPresent = (
372
+ {
373
+ hookPlugin,
374
+ route,
375
+ payload,
376
+ }: {
377
+ hookPlugin: Hook;
378
+ route: string;
379
+ payload: object;
380
+ },
381
+ dispose
382
+ ) => {
378
383
  if (hookPlugin?.lastHook) {
379
384
  dispose();
380
385
  }
@@ -408,9 +413,12 @@ export function NavigationProvider({ children }: Props) {
408
413
  }
409
414
  };
410
415
 
411
- const handleHookCancel = ({ hookPlugin }, dispose) => {
412
- if (hookPlugin?.lastHook) {
413
- dispose();
416
+ const handleHookCancel = ({ hookPlugin, callback }, dispose) => {
417
+ dispose();
418
+ setStartUpHooks(false);
419
+
420
+ if (callback && typeof callback === "function") {
421
+ callback();
414
422
  }
415
423
 
416
424
  if (hookPlugin.isModalHook()) {
@@ -476,7 +484,13 @@ export function NavigationProvider({ children }: Props) {
476
484
  return false;
477
485
  }, [pluginConfigurations, plugins, rivers]);
478
486
 
479
- const [startUpHooks, setStartUpHooks] = React.useState(checkStartUpHooks);
487
+ const [startUpHooks, _setStartUpHooks] = React.useState(checkStartUpHooks);
488
+ const currentStartUpHooks = React.useRef(checkStartUpHooks);
489
+
490
+ const setStartUpHooks = (value) => {
491
+ _setStartUpHooks(value);
492
+ currentStartUpHooks.current = value;
493
+ };
480
494
 
481
495
  const handleHookComplete =
482
496
  (navigationAction, targetRoute, { screen, options }) =>
@@ -484,7 +498,7 @@ export function NavigationProvider({ children }: Props) {
484
498
  if (hookPlugin?.lastHook) {
485
499
  dispose({ disposeAll: true });
486
500
 
487
- startUpHooks && setStartUpHooks(false);
501
+ startUpHooks.current && setStartUpHooks(false);
488
502
  }
489
503
 
490
504
  dispatch(
@@ -593,10 +607,15 @@ export function NavigationProvider({ children }: Props) {
593
607
  targetScreen: screen,
594
608
  rivers,
595
609
  plugins,
596
- startUpHooksData: { startUpHooks, setStartUpHooks },
610
+ startUpHooksData: {
611
+ startUpHooks: currentStartUpHooks.current,
612
+ setStartUpHooks,
613
+ },
597
614
  };
598
615
 
599
- HooksManager(hooksOptions)
616
+ const hooksManager = HooksManager(hooksOptions);
617
+
618
+ hooksManager.subscriber
600
619
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, handleHookPresent)
601
620
  .on(HOOKS_EVENTS.ERROR, handleHookError)
602
621
  .on(HOOKS_EVENTS.CANCEL, handleHookCancel)
@@ -607,39 +626,15 @@ export function NavigationProvider({ children }: Props) {
607
626
  screen,
608
627
  options,
609
628
  })
610
- )
611
- .handleHooks(legacyScreenData({ entry, screen }));
629
+ );
630
+
631
+ hooksManager.handleHooks(legacyScreenData({ entry, screen }));
612
632
  } else {
613
633
  dispatch(navigationAction(targetRoute, { screen, entry, options }));
614
634
  }
615
635
  },
616
636
  });
617
637
 
618
- const openModal = React.useCallback(
619
- ({ item, options = {}, props = {} }: OpenModalArg) => {
620
- setModalState({
621
- visible: true,
622
- screen: item as ZappRiver,
623
- options: {
624
- animated: true,
625
- animationType: "slide",
626
- onShow: () => {},
627
- presentationStyle: "overFullScreen",
628
- transparent: true,
629
- ...options,
630
- onDismiss: () => {
631
- setModalState(initialModalState);
632
- },
633
- onRequestClose: () => {
634
- dismissModal();
635
- },
636
- },
637
- props,
638
- });
639
- },
640
- []
641
- );
642
-
643
638
  const openPiP = React.useCallback(() => {
644
639
  dispatch(setVideoPiP());
645
640
  }, []);
@@ -660,10 +655,6 @@ export function NavigationProvider({ children }: Props) {
660
655
  }
661
656
  }, [state?.options?.videoModal?.previousMode]);
662
657
 
663
- const dismissModal = React.useCallback(() => {
664
- setModalState(() => ({ ...initialModalState }));
665
- }, []);
666
-
667
658
  const openModalBottomSheet = React.useCallback(
668
659
  ({
669
660
  ModalBottomSheetContent,
@@ -695,15 +686,15 @@ export function NavigationProvider({ children }: Props) {
695
686
 
696
687
  // It will only work for the regular stack and pathname, It won't work for modals
697
688
  // TODO: integrate video/hook and regular modal into stack.
698
- const getStackForPathname = React.useCallback((pathname: string):
699
- | NavigationScreenState
700
- | undefined => {
701
- const stack = getStack();
689
+ const getStackForPathname = (
690
+ pathname: string
691
+ ): NavigationScreenState | undefined => {
692
+ const stack = [...state?.stack?.mainStack];
702
693
 
703
694
  const currentStack = stack.find(({ route }) => route === pathname);
704
695
 
705
696
  return currentStack;
706
- }, []);
697
+ };
707
698
 
708
699
  const navigator: QuickBrickAppNavigator = React.useMemo(
709
700
  () => ({
@@ -730,7 +721,7 @@ export function NavigationProvider({ children }: Props) {
730
721
  modalData: state.stack.modal?.state ?? null,
731
722
  openModal,
732
723
  dismissModal,
733
- modalState,
724
+ getModalState,
734
725
  openModalBottomSheet,
735
726
  closeModalBottomSheet,
736
727
  videoModalState: state.options.videoModal,
@@ -747,15 +738,9 @@ export function NavigationProvider({ children }: Props) {
747
738
  replaceTop,
748
739
  getStack,
749
740
  getStackForPathname,
741
+ mainStack: state.stack.mainStack,
750
742
  }),
751
- [
752
- rivers,
753
- plugins,
754
- JSON.stringify(state),
755
- modalState,
756
- appLaunched,
757
- startUpHooks,
758
- ]
743
+ [rivers, plugins, JSON.stringify(state), appLaunched, startUpHooks]
759
744
  );
760
745
 
761
746
  // when running the tests, we pass the dispatch function
@@ -11,7 +11,9 @@ Object {
11
11
  "presentationStyle": "overFullScreen",
12
12
  "transparent": true,
13
13
  },
14
- "props": Object {},
14
+ "props": Object {
15
+ "screenData": Object {},
16
+ },
15
17
  "screen": Object {
16
18
  "id": "A1234",
17
19
  "navigations": Array [],
@@ -30,26 +32,7 @@ Object {
30
32
  }
31
33
  `;
32
34
 
33
- exports[`<NavigationProvider /> modal feature sets the modalState when opening a modal 1`] = `
34
- Object {
35
- "options": Object {
36
- "animated": true,
37
- "animationType": "slide",
38
- "onDismiss": [Function],
39
- "onRequestClose": [Function],
40
- "onShow": [Function],
41
- "presentationStyle": "overFullScreen",
42
- "transparent": true,
43
- },
44
- "props": Object {},
45
- "screen": Object {
46
- "id": "A1234",
47
- "navigations": Array [],
48
- "ui_components": Array [],
49
- },
50
- "visible": true,
51
- }
52
- `;
35
+ exports[`<NavigationProvider /> modal feature sets the modalState when opening a modal 1`] = `undefined`;
53
36
 
54
37
  exports[`<NavigationProvider /> modal feature should reset state to initial when dismissing a modal ( closeModalBottomSheet ) opened by openModalBottomSheet 1`] = `
55
38
  Object {