@applicaster/zapp-react-native-ui-components 15.0.0-alpha.2691570618 → 15.0.0-alpha.2835124704

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.
@@ -17,6 +17,7 @@ import { CellWithFocusable } from "./CellWithFocusable";
17
17
  import { FocusableWrapper } from "./FocusableWrapper";
18
18
 
19
19
  import { focusableButtonsRegistration$ } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux/utils/utils.ios";
20
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
20
21
 
21
22
  type Props = {
22
23
  item: ZappEntry;
@@ -37,6 +38,9 @@ type Props = {
37
38
  component: {
38
39
  id: number | string;
39
40
  component_type: string;
41
+ styles?: {
42
+ component_margin_top?: number;
43
+ };
40
44
  };
41
45
  selected: boolean;
42
46
  CellRenderer: React.FunctionComponent<any> & {
@@ -204,11 +208,16 @@ class TvOSCell extends React.Component<Props, State> {
204
208
  const extraAnchorPointYOffset =
205
209
  screenLayout?.extraAnchorPointYOffset || 0;
206
210
 
211
+ const componentMarginTop = toNumberWithDefaultZero(
212
+ component?.styles?.component_margin_top
213
+ );
214
+
207
215
  const totalOffset =
208
216
  headerOffset +
209
- (componentAnchorPointY || 0) +
210
- extraAnchorPointYOffset -
211
- componentsMapOffset || 0;
217
+ (componentAnchorPointY || 0) +
218
+ extraAnchorPointYOffset -
219
+ (componentsMapOffset || 0) +
220
+ componentMarginTop;
212
221
 
213
222
  mainOffsetUpdater?.(
214
223
  { tag: this.target },
@@ -32,6 +32,7 @@ export default function Image({
32
32
  placeholderImage,
33
33
  entry,
34
34
  withDimensions,
35
+ source: sourceProp,
35
36
  ...otherProps
36
37
  }: Props) {
37
38
  const [showDefault, setShowDefault] = React.useState(false);
@@ -48,7 +49,10 @@ export default function Image({
48
49
  entry,
49
50
  showDefault,
50
51
  placeholderImage: placeholderImage || "",
51
- otherProps,
52
+ otherProps: {
53
+ source: sourceProp,
54
+ state: otherProps.state,
55
+ },
52
56
  });
53
57
 
54
58
  const onError = React.useCallback(() => {
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Image as RnImage, ImageStyle } from "react-native";
3
- import { equals, omit } from "ramda";
3
+ import { equals } from "ramda";
4
4
 
5
5
  import { useImageSource } from "./hooks";
6
6
 
@@ -25,11 +25,19 @@ function Image({
25
25
  placeholderImage,
26
26
  entry,
27
27
  withDimensions,
28
+ source: sourceProp,
28
29
  ...otherProps
29
30
  }: Props) {
30
31
  const [error, setErrorState] = React.useState(null);
31
32
 
32
- const source = useImageSource({ uri, entry, otherProps });
33
+ const source = useImageSource({
34
+ uri,
35
+ entry,
36
+ otherProps: {
37
+ source: sourceProp,
38
+ state: otherProps.state,
39
+ },
40
+ });
33
41
 
34
42
  React.useEffect(() => {
35
43
  // reset error state on URI change as the error is referencing previous uri
@@ -49,7 +57,7 @@ function Image({
49
57
  onError={React.useCallback(() => setErrorState(true), [])}
50
58
  // as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
51
59
  source={_source?.uri ? _source : undefined}
52
- {...omit(["source"], otherProps)}
60
+ {...otherProps}
53
61
  />
54
62
  );
55
63
  }
@@ -23,9 +23,17 @@ function Image({
23
23
  placeholderImage,
24
24
  entry,
25
25
  withDimensions,
26
+ source: sourceProp,
26
27
  ...otherProps
27
28
  }: Props) {
28
- const source = useImageSource({ uri, entry, otherProps });
29
+ const source = useImageSource({
30
+ uri,
31
+ entry,
32
+ otherProps: {
33
+ source: sourceProp,
34
+ state: otherProps.state,
35
+ },
36
+ });
29
37
 
30
38
  const updatedSource = source ? withDimensions(source) : { uri: "" };
31
39
 
@@ -1,5 +1,4 @@
1
1
  import * as React from "react";
2
- import { path } from "ramda";
3
2
 
4
3
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
5
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
@@ -7,13 +6,16 @@ import { extractAsset } from "./utils";
7
6
 
8
7
  type Return = { uri: string } | null;
9
8
 
10
- const getSourceContext = path(["source", "context"]);
11
- const getSourceUri = path(["source", "uri"]);
12
- const getState = path(["state"]);
9
+ const getSourceContext = (source) => source?.context;
10
+ const getSourceUri = (source) => source?.uri;
13
11
 
14
- export const useImageSource = ({ uri, entry, otherProps }): Return => {
15
- const uriContext = getSourceContext(otherProps);
16
- const uriState = getState(otherProps);
12
+ export const useImageSource = ({
13
+ uri,
14
+ entry,
15
+ otherProps: { source, state },
16
+ }): Return => {
17
+ const uriContext = getSourceContext(source);
18
+ const uriState = state;
17
19
 
18
20
  const action = useActions(uriContext);
19
21
 
@@ -38,7 +40,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
38
40
  return { uri };
39
41
  }
40
42
 
41
- const uriFromSource = getSourceUri(otherProps);
43
+ const uriFromSource = getSourceUri(source);
42
44
 
43
45
  if (uriFromSource) {
44
46
  return { uri: uriFromSource };
@@ -47,7 +49,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
47
49
  return null;
48
50
  };
49
51
 
50
- const getSource = (uri, showDefault, placeholderImage, otherProps) => {
52
+ const getSource = (uri, showDefault, placeholderImage, source) => {
51
53
  const placeholderName = placeholderImage || "";
52
54
 
53
55
  const defaultPath = {
@@ -60,7 +62,7 @@ const getSource = (uri, showDefault, placeholderImage, otherProps) => {
60
62
  return { uri };
61
63
  }
62
64
 
63
- const uriFromSource = getSourceUri(otherProps);
65
+ const uriFromSource = getSourceUri(source);
64
66
 
65
67
  if (uriFromSource) {
66
68
  return { uri: uriFromSource };
@@ -74,10 +76,10 @@ export const useImageSourceWithDefault = ({
74
76
  entry,
75
77
  showDefault,
76
78
  placeholderImage,
77
- otherProps,
79
+ otherProps: { state, source },
78
80
  }): Return => {
79
- const uriContext = getSourceContext(otherProps);
80
- const uriState = getState(otherProps);
81
+ const uriContext = getSourceContext(source);
82
+ const uriState = state;
81
83
 
82
84
  const action = useActions(uriContext);
83
85
 
@@ -98,5 +100,5 @@ export const useImageSourceWithDefault = ({
98
100
  return extractAsset(!isTV(), entryStateLocal.asset, uriState);
99
101
  }
100
102
 
101
- return getSource(uri, showDefault, placeholderImage, otherProps);
103
+ return getSource(uri, showDefault, placeholderImage, source);
102
104
  };
@@ -1,62 +1,155 @@
1
- import React, { useEffect, useMemo } from "react";
1
+ import React, { useMemo } from "react";
2
2
  import { Animated, Dimensions } from "react-native";
3
3
 
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
5
 
6
6
  import { useConfiguration } from "../utils";
7
- import { useIsTabletLandscape } from "@applicaster/zapp-react-native-utils/reactHooks/device/useMemoizedIsTablet";
7
+ import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
8
+ import { isMenuVisible } from "../../Screen/navigationHandler";
9
+
10
+ import {
11
+ useSafeAreaFrame,
12
+ useSafeAreaInsets,
13
+ } from "react-native-safe-area-context";
14
+ import {
15
+ isAndroidPlatform,
16
+ isAndroidVersionAtLeast,
17
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
18
+ import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
19
+ import { PROGRESS_BAR_HEIGHT } from "./utils";
20
+ import { useIsTablet as getIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
21
+ import { useAppSelector } from "@applicaster/zapp-react-native-redux";
8
22
 
9
23
  export type ModalAnimationContextT = {
10
- yTranslate: React.MutableRefObject<Animated.Value | null>;
24
+ yTranslate: React.MutableRefObject<Animated.AnimatedInterpolation<number>>;
25
+ offsetAnimatedValueRef: React.MutableRefObject<Animated.Value>;
26
+ offset: React.MutableRefObject<number>;
27
+ heightAboveMinimised: number;
28
+ gestureTranslationRef: React.MutableRefObject<Animated.Value>;
11
29
  minimisedHeight: number;
12
30
  };
13
31
 
14
32
  export const ReactContext = React.createContext<ModalAnimationContextT>({
15
33
  yTranslate: React.createRef<Animated.Value | null>(),
34
+ offsetAnimatedValueRef: React.createRef<Animated.Value>(),
35
+ offset: React.createRef<number>(),
36
+ heightAboveMinimised: 0,
37
+ gestureTranslationRef: React.createRef<Animated.Value>(),
16
38
  minimisedHeight: 60,
17
39
  });
18
40
 
41
+ const SAFE_AREA_BREAKING_API_VERSION = 35;
42
+
43
+ export const isOldAndroidDevice =
44
+ isAndroidPlatform() &&
45
+ !isAndroidVersionAtLeast(SAFE_AREA_BREAKING_API_VERSION);
46
+
47
+ const bottomTabBarHeight = getTabBarHeight();
48
+
19
49
  const Provider = ({ children }: { children: React.ReactNode }) => {
50
+ const { height } = Dimensions.get("window");
51
+
20
52
  const yTranslate = React.useRef(
21
- new Animated.Value(Dimensions.get("window").height)
53
+ new Animated.Value(height).interpolate<number>({
54
+ inputRange: [0, height],
55
+ outputRange: [0, height],
56
+ })
22
57
  );
23
58
 
59
+ const { minimised_height: minimisedHeight } = useConfiguration();
60
+
24
61
  const {
25
- videoModalState: { visible },
62
+ videoModalState: { visible, mode },
63
+ currentRoute,
64
+ screenData,
26
65
  } = useNavigation();
27
66
 
28
- const { minimised_height: minimisedHeight } = useConfiguration();
67
+ const isTabletPortrait = useAppSelector(
68
+ (state) => state.appData.isTabletPortrait
69
+ );
70
+
71
+ const plugins = usePlugins();
72
+
73
+ const menuVisible = isMenuVisible(currentRoute, screenData, plugins);
74
+
75
+ const frame = useSafeAreaFrame();
76
+ const insets = useSafeAreaInsets();
77
+
78
+ const [heightAboveMinimised, setHeightAboveMinimised] = React.useState(0);
79
+
80
+ // memoizing heightAboveMinimised value
81
+ const offset = React.useRef(heightAboveMinimised);
82
+
83
+ // Used for memoizing modal y position after start/end of transition
84
+ const offsetAnimatedValueRef = React.useRef(
85
+ new Animated.Value(-offset.current)
86
+ );
87
+
88
+ // Used for gesture handling
89
+ const gestureTranslationRef = React.useRef(new Animated.Value(0));
90
+
91
+ const videoModalStateRef = React.useRef({ visible, mode });
92
+
93
+ React.useEffect(() => {
94
+ videoModalStateRef.current = { visible, mode };
95
+ }, [visible, mode]);
96
+
97
+ const translateY = useMemo(() => {
98
+ const maxRange = heightAboveMinimised;
99
+
100
+ const combined: Animated.AnimatedAddition<number> = Animated.add(
101
+ offsetAnimatedValueRef.current,
102
+ gestureTranslationRef.current
103
+ );
104
+
105
+ return combined.interpolate({
106
+ inputRange: [0, maxRange],
107
+ outputRange: [0, maxRange],
108
+ extrapolate: "clamp",
109
+ });
110
+ }, [visible, heightAboveMinimised]);
111
+
112
+ offset.current = heightAboveMinimised;
113
+ yTranslate.current = translateY;
114
+
115
+ React.useEffect(() => {
116
+ const collapsedHeight =
117
+ minimisedHeight +
118
+ (menuVisible ? bottomTabBarHeight : 0) +
119
+ (isOldAndroidDevice ? 0 : insets.bottom) + // insets.bottom is added to properly display docked modal
120
+ PROGRESS_BAR_HEIGHT;
121
+
122
+ const heightAboveMinimised = frame.height - collapsedHeight;
123
+
124
+ const isLandscape = frame.width > frame.height;
125
+
126
+ const isTablet = getIsTablet();
127
+
128
+ const shouldIgnoreLandscape = isTablet ? isTabletPortrait : true;
29
129
 
30
- const isTabletLandscape = useIsTabletLandscape();
31
- const windowDimensions = Dimensions.get("window");
32
-
33
- useEffect(() => {
34
- // Reset player animation state when video modal is closed
35
- if (!visible) {
36
- if (!isTabletLandscape) {
37
- // restore to portrait ( in portrait mode height is bigger)
38
- if (windowDimensions.height > windowDimensions.width) {
39
- yTranslate.current?.setValue(windowDimensions.height);
40
- }
41
- } else {
42
- yTranslate.current?.setValue(windowDimensions.height);
43
- }
130
+ if (
131
+ heightAboveMinimised !== offset.current &&
132
+ videoModalStateRef.current.mode !== "PIP" &&
133
+ videoModalStateRef.current.mode !== "FULLSCREEN"
134
+ ) {
135
+ if (isLandscape && shouldIgnoreLandscape) return;
136
+ setHeightAboveMinimised(heightAboveMinimised);
137
+ offset.current = heightAboveMinimised;
44
138
  }
45
- }, [
46
- visible,
47
- windowDimensions.height,
48
- isTabletLandscape,
49
- windowDimensions.width,
50
- ]);
139
+ }, [frame.height, insets.bottom, menuVisible, minimisedHeight]);
51
140
 
52
141
  return (
53
142
  <ReactContext.Provider
54
143
  value={useMemo(
55
144
  () => ({
56
145
  yTranslate,
146
+ offsetAnimatedValueRef,
147
+ offset,
148
+ heightAboveMinimised,
57
149
  minimisedHeight,
150
+ gestureTranslationRef,
58
151
  }),
59
- [minimisedHeight]
152
+ [minimisedHeight, heightAboveMinimised]
60
153
  )}
61
154
  >
62
155
  {children}
@@ -139,11 +139,7 @@ const VideoModalComponent = () => {
139
139
 
140
140
  {itemIdHooksFinished === item?.id ? (
141
141
  <View pointerEvents="box-none" style={styles.container}>
142
- <HandlePlayable
143
- item={item}
144
- isModal={mode !== "PIP"}
145
- mode={mode}
146
- />
142
+ <HandlePlayable item={item} isModal mode={mode} />
147
143
  </View>
148
144
  ) : (
149
145
  <View style={styles.loaderContainer}>
@@ -79,7 +79,7 @@ export const getPlayerDimensions = (
79
79
  ): ViewStyle => ({
80
80
  ...(baseDimensions as any),
81
81
  width: baseDimensions.width,
82
- aspectRatio: aspectRatio,
82
+ aspectRatio,
83
83
  });
84
84
 
85
85
  export const getContainerDimensions = (
@@ -87,5 +87,5 @@ export const getContainerDimensions = (
87
87
  aspectRatio?: string | number
88
88
  ): ViewStyle => ({
89
89
  ...baseDimensions,
90
- aspectRatio: aspectRatio,
90
+ aspectRatio,
91
91
  });
@@ -4,6 +4,7 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
5
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
6
6
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
7
+ import { create } from "zustand";
7
8
 
8
9
  export const useConfiguration = () => {
9
10
  const {
@@ -52,6 +53,12 @@ export const useConfiguration = () => {
52
53
  };
53
54
  };
54
55
 
56
+ export const useAnimationStateStore = create<{
57
+ isAnimationInProgress: boolean;
58
+ }>(() => ({
59
+ isAnimationInProgress: false,
60
+ }));
61
+
55
62
  const fullSize = {
56
63
  width: "100%",
57
64
  height: "100%",
@@ -76,7 +76,7 @@ export function StaticFeedResolver({
76
76
 
77
77
  const zappPipesDataProps = useMemo(
78
78
  () => ({
79
- zappPipesData: { url, loading, data, error },
79
+ zappPipesData: { url, loading, data, error }, // todo: add applyItemLimit
80
80
  reloadData,
81
81
  loadNextData: undefined, // Static resolver doesn't support pagination
82
82
  }),
@@ -3,6 +3,10 @@ import * as R from "ramda";
3
3
  export function itemLimitForData(entry = [], component) {
4
4
  const itemLimitValue = Number(R.path(["rules", "item_limit"], component));
5
5
 
6
+ if (!itemLimitValue) {
7
+ return entry;
8
+ }
9
+
6
10
  const itemLimit =
7
11
  itemLimitValue && itemLimitValue > 0
8
12
  ? itemLimitValue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "15.0.0-alpha.2691570618",
3
+ "version": "15.0.0-alpha.2835124704",
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",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "15.0.0-alpha.2691570618",
32
- "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.2691570618",
33
- "@applicaster/zapp-react-native-redux": "15.0.0-alpha.2691570618",
34
- "@applicaster/zapp-react-native-utils": "15.0.0-alpha.2691570618",
31
+ "@applicaster/applicaster-types": "15.0.0-alpha.2835124704",
32
+ "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.2835124704",
33
+ "@applicaster/zapp-react-native-redux": "15.0.0-alpha.2835124704",
34
+ "@applicaster/zapp-react-native-utils": "15.0.0-alpha.2835124704",
35
35
  "promise": "^8.3.0",
36
36
  "url": "^0.11.0",
37
37
  "uuid": "^3.3.2"