@applicaster/zapp-react-native-ui-components 12.0.0-alpha.5468407101 → 12.0.0-alpha.5471145113

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.
Files changed (53) hide show
  1. package/Components/BaseFocusable/index.tsx +1 -1
  2. package/Components/Cell/Cell.tsx +5 -5
  3. package/Components/Cell/CellWithFocusable.tsx +17 -5
  4. package/Components/FocusableGroup/index.tsx +1 -0
  5. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  6. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  7. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  8. package/Components/Layout/TV/__tests__/index.test.tsx +19 -75
  9. package/Components/Layout/TV/index.tsx +12 -11
  10. package/Components/Layout/TV/index.web.tsx +33 -0
  11. package/Components/Layout/index.tsx +15 -11
  12. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  13. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -109
  14. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  15. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  16. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  17. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  18. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  19. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
  20. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  21. package/Components/MasterCell/utils/index.ts +12 -29
  22. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  23. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  24. package/Components/Navigator/StackNavigator.tsx +48 -0
  25. package/Components/Navigator/index.ts +1 -0
  26. package/Components/PlayerContainer/PlayerContainer.tsx +8 -1
  27. package/Components/River/ComponentsMap/ComponentsMap.tsx +6 -0
  28. package/Components/River/RefreshControl.tsx +2 -2
  29. package/Components/River/TV/River.tsx +0 -23
  30. package/Components/RouteManager/index.tsx +2 -2
  31. package/Components/Screen/TV/hooks/index.ts +3 -0
  32. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  33. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  34. package/Components/Screen/TV/index.web.tsx +179 -0
  35. package/Components/Screen/__tests__/Screen.test.tsx +3 -0
  36. package/Components/Screen/index.tsx +29 -1
  37. package/Components/ScreenResolver/index.tsx +3 -1
  38. package/Components/Transitioner/Scene.tsx +24 -19
  39. package/Components/Transitioner/Transitioner.tsx +21 -28
  40. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  41. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  42. package/Components/VideoLive/LiveImageManager.ts +18 -1
  43. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  44. package/Components/VideoModal/PlayerWrapper.tsx +67 -60
  45. package/Components/VideoModal/VideoModal.tsx +4 -4
  46. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  47. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  48. package/Contexts/ScreenContext/index.tsx +6 -0
  49. package/Contexts/ScreenDataContext/index.tsx +20 -0
  50. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  51. package/events/index.ts +1 -0
  52. package/package.json +5 -5
  53. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
@@ -42,12 +42,12 @@ export const PlayerDetails = ({
42
42
  : {};
43
43
 
44
44
  // Animation setup
45
- const translateY = useRef(new Animated.Value(100)).current;
45
+ const translateY = useRef(new Animated.Value(50)).current;
46
46
  const opacity = useRef(new Animated.Value(0)).current;
47
47
 
48
48
  const runAnimation = () => {
49
49
  Animated.timing(translateY, {
50
- toValue: 0,
50
+ toValue: -30,
51
51
  duration: 500,
52
52
  easing: Easing.inOut(Easing.ease),
53
53
  useNativeDriver: true,
@@ -63,7 +63,7 @@ export const PlayerDetails = ({
63
63
 
64
64
  useEffect(() => {
65
65
  if (isAudioPlayer) {
66
- setTimeout(() => runAnimation(), 1000);
66
+ setTimeout(() => runAnimation(), 1500);
67
67
  }
68
68
  }, [isAudioPlayer]);
69
69
 
@@ -14,12 +14,13 @@ import { PlayerDetails } from "./PlayerDetails";
14
14
  import { playerDimesionsHack } from "./utils";
15
15
  import { PathnameContext } from "../../Contexts/PathnameContext";
16
16
  import { ScreenContextProvider } from "../../Contexts/ScreenContext";
17
+ import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
17
18
 
18
19
  import {
19
- AnimationComponent,
20
- ComponentAnimationType,
21
20
  AnimatedScrollModal,
22
21
  AnimatedVideoPlayerComponent,
22
+ AnimationComponent,
23
+ ComponentAnimationType,
23
24
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
24
25
 
25
26
  type DimensionsT = {
@@ -180,65 +181,71 @@ export const PlayerWrapper = (props: Props) => {
180
181
  [containerDimensions, playerDimesionsHack]
181
182
  );
182
183
 
184
+ const pathname = `${ROUTE_TYPES.VIDEO_MODAL}/${entry?.id}`;
185
+
183
186
  return (
184
- <WrapperView
185
- edges={getEdges(isTablet, isInlineModal) as readonly Edge[]}
186
- style={[
187
- safeAreaStyles(configuration, isTablet),
188
- style,
189
- playerDimesionsHack,
190
- ]}
191
- >
192
- <AnimationComponent
193
- animationType={ComponentAnimationType.moveUpComponent}
194
- additionalData={{ saveArea: true }}
195
- style={directionStyles(isTabletLandscape)}
196
- >
197
- <ScreenContextProvider pathname={"videoModal"}>
198
- <PathnameContext.Provider value={"videoModal"}>
199
- <View
200
- testID={`${entry?.id}-player-container`}
201
- style={[
202
- defaultStyles.playerContainer,
203
- containerDimensions,
204
- containerStyle,
205
- playerDimesionsHack,
206
- ]}
207
- >
208
- <AnimationComponent
209
- animationType={ComponentAnimationType.moveUpComponent}
210
- style={isTabletLandscape ? defaultStyles.flex : undefined}
211
- additionalData={{
212
- useLayoutMeasure: isTabletLandscape,
213
- disableAnimatedComponent: !isTabletLandscape,
214
- resetAnimationValue: isTabletLandscape && docked,
215
- }}
216
- >
217
- <AnimatedVideoPlayerComponent>
218
- {children(childrenStyles)}
219
- </AnimatedVideoPlayerComponent>
220
- </AnimationComponent>
221
- </View>
222
- <AnimatedScrollModal>
223
- {isInlineModal ? (
224
- <AnimationComponent
225
- animationType={ComponentAnimationType.componentFade}
226
- style={defaultStyles.flex}
187
+ <PathnameContext.Provider value={pathname}>
188
+ <ScreenContextProvider pathname={pathname}>
189
+ <WrapperView
190
+ edges={getEdges(isTablet, isInlineModal) as readonly Edge[]}
191
+ style={[
192
+ safeAreaStyles(configuration, isTablet),
193
+ style,
194
+ playerDimesionsHack,
195
+ ]}
196
+ >
197
+ <AnimationComponent
198
+ animationType={ComponentAnimationType.moveUpComponent}
199
+ additionalData={{ saveArea: true }}
200
+ style={directionStyles(isTabletLandscape)}
201
+ >
202
+ <PathnameContext.Provider value={pathname}>
203
+ <ScreenContextProvider pathname={pathname}>
204
+ <View
205
+ testID={`${entry?.id}-player-container`}
206
+ style={[
207
+ defaultStyles.playerContainer,
208
+ containerDimensions,
209
+ containerStyle,
210
+ playerDimesionsHack,
211
+ ]}
227
212
  >
228
- <PlayerDetails
229
- configuration={configuration}
230
- style={defaultStyles.playerDetails}
231
- entry={entry}
232
- isTabletLandscape={isTabletLandscape}
233
- />
234
- </AnimationComponent>
235
- ) : (
236
- <View style={defaultStyles.playerDetails} />
237
- )}
238
- </AnimatedScrollModal>
239
- </PathnameContext.Provider>
240
- </ScreenContextProvider>
241
- </AnimationComponent>
242
- </WrapperView>
213
+ <AnimationComponent
214
+ animationType={ComponentAnimationType.moveUpComponent}
215
+ style={isTabletLandscape ? defaultStyles.flex : undefined}
216
+ additionalData={{
217
+ useLayoutMeasure: isTabletLandscape,
218
+ disableAnimatedComponent: !isTabletLandscape,
219
+ resetAnimationValue: isTabletLandscape && docked,
220
+ }}
221
+ >
222
+ <AnimatedVideoPlayerComponent>
223
+ {children(childrenStyles)}
224
+ </AnimatedVideoPlayerComponent>
225
+ </AnimationComponent>
226
+ </View>
227
+ <AnimatedScrollModal>
228
+ {isInlineModal ? (
229
+ <AnimationComponent
230
+ animationType={ComponentAnimationType.componentFade}
231
+ style={defaultStyles.flex}
232
+ >
233
+ <PlayerDetails
234
+ configuration={configuration}
235
+ style={defaultStyles.playerDetails}
236
+ entry={entry}
237
+ isTabletLandscape={isTabletLandscape}
238
+ />
239
+ </AnimationComponent>
240
+ ) : (
241
+ <View style={defaultStyles.playerDetails} />
242
+ )}
243
+ </AnimatedScrollModal>
244
+ </ScreenContextProvider>
245
+ </PathnameContext.Provider>
246
+ </AnimationComponent>
247
+ </WrapperView>
248
+ </ScreenContextProvider>
249
+ </PathnameContext.Provider>
243
250
  );
244
251
  };
@@ -129,8 +129,8 @@ const VideoModalComponent = () => {
129
129
  const pathname = `${ROUTE_TYPES.VIDEO_MODAL}/${item?.id}`;
130
130
 
131
131
  return (
132
- <ScreenContextProvider pathname={pathname}>
133
- <PathnameContext.Provider value={pathname}>
132
+ <PathnameContext.Provider value={pathname}>
133
+ <ScreenContextProvider pathname={pathname}>
134
134
  {itemIdHooksFinished === item?.id ? (
135
135
  <AnimatedPlayerModalWrapper
136
136
  style={[
@@ -153,8 +153,8 @@ const VideoModalComponent = () => {
153
153
  <Spinner />
154
154
  </View>
155
155
  )}
156
- </PathnameContext.Provider>
157
- </ScreenContextProvider>
156
+ </ScreenContextProvider>
157
+ </PathnameContext.Provider>
158
158
  );
159
159
  };
160
160
 
@@ -25,6 +25,13 @@ jest.mock("react-native-gesture-handler");
25
25
 
26
26
  jest.mock("../PlayerDetails", () => ({ PlayerDetails: View }));
27
27
 
28
+ jest.mock(
29
+ "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext",
30
+ () => ({
31
+ useScreenContext: jest.fn().mockReturnValue({ screen: {}, entry: {} }),
32
+ })
33
+ );
34
+
28
35
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/device", () => ({
29
36
  useIsTablet,
30
37
  }));
@@ -6,23 +6,23 @@ import { callOnChildren } from "../utils";
6
6
 
7
7
  export function ViewportTracker(props) {
8
8
  const viewportEvents = useViewportEventsContext();
9
- const { children } = props;
10
- const [width, setWidth] = React.useState(0);
11
- const [height, setHeight] = React.useState(0);
12
- const [offsetX, setOffsetX] = React.useState(0);
13
- const [offsetY, setOffsetY] = React.useState(0);
14
9
  const [nodeHandle, setNodeHandle] = React.useState(null);
15
10
 
16
- const assignRef = React.useCallback(
17
- (ref) => {
18
- children?.ref?.(ref);
19
- setNodeHandle(findNodeHandle(ref));
20
- },
21
- [children]
22
- );
11
+ const childrenRef = React.useRef(props.children);
12
+
13
+ const dimensionsRef = React.useRef({ width: 0, height: 0 });
14
+ const offsetRef = React.useRef({ offsetX: 0, offsetY: 0 });
15
+
16
+ const assignRef = React.useCallback((ref) => {
17
+ childrenRef.current?.ref?.(ref);
18
+ setNodeHandle(findNodeHandle(ref));
19
+ }, []);
23
20
 
24
21
  const onViewportChange = React.useCallback(
25
- (event, shouldMeasureLayout = true) => {
22
+ ({
23
+ event = { ...dimensionsRef.current, ...offsetRef.current },
24
+ shouldMeasureLayout = true,
25
+ } = {}) => {
26
26
  if (nodeHandle && event?.width > 0 && event?.height > 0) {
27
27
  viewportEvents?.notify?.({
28
28
  parentHandle: nodeHandle,
@@ -36,54 +36,45 @@ export function ViewportTracker(props) {
36
36
 
37
37
  const onLayout = React.useCallback(
38
38
  (event) => {
39
- callOnChildren(children, "onLayout", event);
40
- setWidth(event?.nativeEvent?.layout?.width);
41
- setHeight(event?.nativeEvent?.layout?.height);
39
+ callOnChildren(childrenRef.current, "onLayout", event);
40
+ dimensionsRef.current = event?.nativeEvent?.layout;
42
41
 
43
- onViewportChange({
44
- width: event?.nativeEvent?.layout?.width,
45
- height: event?.nativeEvent?.layout?.height,
46
- offsetX,
47
- offsetY,
48
- });
42
+ onViewportChange();
49
43
  },
50
- [offsetX, offsetY, children, onViewportChange]
44
+ [onViewportChange]
51
45
  );
52
46
 
53
47
  const onContentSizeChange = React.useCallback(
54
48
  (contentWidth, contentHeight) => {
55
49
  callOnChildren(
56
- children,
50
+ childrenRef.current,
57
51
  "onContentSizeChange",
58
52
  contentWidth,
59
53
  contentHeight
60
54
  );
61
55
 
62
- onViewportChange({ width, height, offsetX, offsetY });
56
+ onViewportChange();
63
57
  },
64
- [onViewportChange, children, width, height, offsetX, offsetY]
58
+ [onViewportChange]
65
59
  );
66
60
 
67
61
  const onScroll = React.useCallback(
68
62
  (event) => {
69
- callOnChildren(children, "onScroll", event);
70
- setOffsetX(event?.nativeEvent?.contentOffset?.x);
71
- setOffsetY(event?.nativeEvent?.contentOffset?.y);
63
+ callOnChildren(childrenRef.current, "onScroll", event);
64
+ offsetRef.current = event?.nativeEvent?.contentOffset;
72
65
 
73
- onViewportChange(
74
- {
75
- width,
76
- height,
77
- offsetX: event?.nativeEvent?.contentOffset?.x,
78
- offsetY: event?.nativeEvent?.contentOffset?.y,
79
- },
80
- false
81
- );
66
+ onViewportChange({
67
+ shouldMeasureLayout: false,
68
+ });
82
69
  },
83
- [onViewportChange, width, height, children]
70
+ [onViewportChange]
84
71
  );
85
72
 
86
- return React.cloneElement(React.Children.only(children), {
73
+ React.useEffect(() => {
74
+ childrenRef.current = props.children;
75
+ }, [props.children]);
76
+
77
+ return React.cloneElement(React.Children.only(props.children), {
87
78
  ref: assignRef,
88
79
  onLayout,
89
80
  onContentSizeChange,
@@ -2,6 +2,7 @@ import React, {
2
2
  createContext,
3
3
  ReactNode,
4
4
  useCallback,
5
+ useEffect,
5
6
  useMemo,
6
7
  useRef,
7
8
  } from "react";
@@ -113,6 +114,11 @@ export function ScreenContextProvider({
113
114
  return navBarState;
114
115
  }, []);
115
116
 
117
+ useEffect(() => {
118
+ // purge the getScreenNavBarState store when the pathname changes
119
+ screenNavBarStateRef.current = null;
120
+ }, [pathname]);
121
+
116
122
  const screenNavBarState = getScreenNavBarState()(
117
123
  useShallow((state) => ({
118
124
  visible: state.visible,
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
3
+
4
+ export const ScreenDataContext = React.createContext<any>(null);
5
+
6
+ // Use this only to provide initial screenData context, before the Transitioner and Screen is rendered.
7
+ export const withScreenDataContextProvider = (Component: any) => {
8
+ return function ScreenDataContextProvider(props: any) {
9
+ const { activeRiver } = useNavigation();
10
+
11
+ // use only initial activeRiver as this context should only be used for "Home", initial route
12
+ const screenData = React.useMemo(() => ({ screen: activeRiver }), []);
13
+
14
+ return (
15
+ <ScreenDataContext.Provider value={screenData}>
16
+ <Component {...props} />
17
+ </ScreenDataContext.Provider>
18
+ );
19
+ };
20
+ };
@@ -63,7 +63,7 @@ function prepareContext(
63
63
  const parent = findParent(currentContext, route, getChildren);
64
64
 
65
65
  const newEntry = {
66
- route: route,
66
+ route,
67
67
  id: uuid(),
68
68
  data: newContext,
69
69
  } as SingleEntry;
package/events/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export enum QBUIComponentEvents {
2
2
  toggleGradient = "toggleGradient",
3
3
  topMenuBarTV_onFocus = "topMenuBarTV_onFocus",
4
+ navigatorReplaceItem = "navigatorReplaceItem",
4
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "12.0.0-alpha.5468407101",
3
+ "version": "12.0.0-alpha.5471145113",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -34,10 +34,10 @@
34
34
  "redux-mock-store": "^1.5.3"
35
35
  },
36
36
  "dependencies": {
37
- "@applicaster/applicaster-types": "12.0.0-alpha.5468407101",
38
- "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.5468407101",
39
- "@applicaster/zapp-react-native-redux": "12.0.0-alpha.5468407101",
40
- "@applicaster/zapp-react-native-utils": "12.0.0-alpha.5468407101",
37
+ "@applicaster/applicaster-types": "12.0.0-alpha.5471145113",
38
+ "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.5471145113",
39
+ "@applicaster/zapp-react-native-redux": "12.0.0-alpha.5471145113",
40
+ "@applicaster/zapp-react-native-utils": "12.0.0-alpha.5471145113",
41
41
  "promise": "^8.3.0",
42
42
  "react-router-native": "^5.1.2",
43
43
  "url": "^0.11.0",
@@ -1,64 +0,0 @@
1
- import * as React from "react";
2
- import { View, StyleSheet } from "react-native";
3
- import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
4
- import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
5
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
- import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
7
- import { Spinner } from "@applicaster/zapp-react-native-ui-components/Components/Spinner";
8
- import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
9
-
10
- import { useScreenConfiguration } from "../../River/useScreenConfiguration";
11
-
12
- const styles = StyleSheet.create({
13
- container: {
14
- position: "absolute",
15
- top: 0,
16
- left: 0,
17
- right: 0,
18
- bottom: 0,
19
-
20
- alignItems: "center",
21
- justifyContent: "center",
22
- },
23
- });
24
-
25
- export const TransitionOverlay = () => {
26
- const screen = useCurrentScreenData();
27
-
28
- const { backgroundColor: screenBackgroundColor } = useScreenConfiguration(
29
- screen?.id
30
- );
31
-
32
- const theme = useTheme();
33
-
34
- const themeBackgroundColor = React.useMemo(
35
- () => theme.app_background_color,
36
- [theme.app_background_color]
37
- );
38
-
39
- const backgroundColor = ifEmptyUseFallback(
40
- screenBackgroundColor,
41
- themeBackgroundColor
42
- );
43
-
44
- const {
45
- appState: { isTransitioning },
46
- } = usePickFromState(["appState"]);
47
-
48
- if (!isWeb() || !isTransitioning) {
49
- return null;
50
- }
51
-
52
- return (
53
- <View
54
- style={[
55
- styles.container,
56
- {
57
- backgroundColor,
58
- },
59
- ]}
60
- >
61
- <Spinner size={"large"} />
62
- </View>
63
- );
64
- };