@applicaster/zapp-react-native-ui-components 15.0.0-alpha.2349550201 → 15.0.0-alpha.2413435535

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 },
@@ -9,6 +9,7 @@ import { useTrackCurrentAutoScrollingElement } from "@applicaster/zapp-react-nat
9
9
  import { useUIComponentContext } from "@applicaster/zapp-react-native-ui-components/Contexts/UIComponentContext";
10
10
  import { getPropComponentType } from "@applicaster/zapp-react-native-utils/cellUtils";
11
11
  import { findPluginByIdentifier } from "@applicaster/zapp-react-native-utils/pluginUtils";
12
+ import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
12
13
 
13
14
  type LiveImageProps = {
14
15
  item: ZappEntry;
@@ -108,8 +109,7 @@ const prepareEntry = (entry) => {
108
109
  };
109
110
  }
110
111
 
111
- const previewPlayback =
112
- entry.extensions?.["brightcove"]?.["preview_playback"];
112
+ const previewPlayback = entry.extensions?.brightcove?.preview_playback;
113
113
 
114
114
  if (previewPlayback) {
115
115
  return {
@@ -117,14 +117,14 @@ const prepareEntry = (entry) => {
117
117
  extensions: {
118
118
  ...entry.extensions,
119
119
  brightcove: {
120
- ...entry?.extensions?.["brightcove"],
120
+ ...entry?.extensions?.brightcove,
121
121
  video_id: previewPlayback,
122
122
  },
123
123
  },
124
124
  };
125
125
  }
126
126
 
127
- if (entry.extensions?.["brightcove"]?.["video_id"]) {
127
+ if (entry.extensions?.brightcove?.video_id) {
128
128
  return entry;
129
129
  }
130
130
 
@@ -174,7 +174,7 @@ const getPlayerConfig = (player_screen_id, actionIdentifier) => {
174
174
  // TODO: Add more dict if needed from the screen component, styles, data etc
175
175
  return {
176
176
  playerPluginId: playerScreen?.type ?? DEFAULT_PLAYER_IDENTIFIER,
177
- screenConfig: playerScreen?.["general"],
177
+ screenConfig: playerScreen?.general,
178
178
  };
179
179
  }
180
180
 
@@ -206,6 +206,11 @@ const LiveImageComponent = (props: LiveImageProps) => {
206
206
  state,
207
207
  } = props;
208
208
 
209
+ const accessibilityManager = useAccessibilityManager();
210
+
211
+ const isScreenReaderEnabled =
212
+ accessibilityManager.accessibilityManagerState.screenReaderEnabled;
213
+
209
214
  const component = useUIComponentContext();
210
215
 
211
216
  // Fix for blinking on state change
@@ -239,7 +244,8 @@ const LiveImageComponent = (props: LiveImageProps) => {
239
244
  getFocusedState(state, componentType, isCurrentlyFocused) &&
240
245
  playableEntry &&
241
246
  cellUUID &&
242
- isSupportedTVForLiveImage();
247
+ isSupportedTVForLiveImage() &&
248
+ !isScreenReaderEnabled;
243
249
 
244
250
  return (
245
251
  <>
@@ -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}>
@@ -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%",
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.2349550201",
3
+ "version": "15.0.0-alpha.2413435535",
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.2349550201",
32
- "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.2349550201",
33
- "@applicaster/zapp-react-native-redux": "15.0.0-alpha.2349550201",
34
- "@applicaster/zapp-react-native-utils": "15.0.0-alpha.2349550201",
31
+ "@applicaster/applicaster-types": "15.0.0-alpha.2413435535",
32
+ "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.2413435535",
33
+ "@applicaster/zapp-react-native-redux": "15.0.0-alpha.2413435535",
34
+ "@applicaster/zapp-react-native-utils": "15.0.0-alpha.2413435535",
35
35
  "promise": "^8.3.0",
36
36
  "url": "^0.11.0",
37
37
  "uuid": "^3.3.2"