@applicaster/zapp-react-native-ui-components 13.0.0-alpha.9946926334 → 13.0.0-rc.100

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 (172) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AudioPlayer/AudioPlayer.tsx +7 -0
  3. package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
  4. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +54 -111
  5. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +36 -20
  6. package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
  7. package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
  8. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
  9. package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
  10. package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
  11. package/Components/AudioPlayer/__tests__/title.test.js +3 -5
  12. package/Components/AudioPlayer/helpers.tsx +1 -0
  13. package/Components/BaseFocusable/index.ios.ts +1 -1
  14. package/Components/BaseFocusable/index.tsx +2 -3
  15. package/Components/Cell/Cell.tsx +11 -16
  16. package/Components/Cell/CellWithFocusable.tsx +50 -59
  17. package/Components/Cell/CellWrapper.tsx +18 -0
  18. package/Components/Cell/TvOSCellComponent.tsx +20 -26
  19. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  20. package/Components/Cell/index.js +3 -1
  21. package/Components/Cell/styles.ts +17 -0
  22. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +46 -48
  23. package/Components/CellRendererResolver/index.ts +2 -1
  24. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  25. package/Components/ComponentResolver/__tests__/componentResolver.test.js +16 -22
  26. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  27. package/Components/ErrorScreen/index.tsx +14 -6
  28. package/Components/Focusable/Focusable.tsx +1 -0
  29. package/Components/Focusable/FocusableTvOS.tsx +6 -2
  30. package/Components/Focusable/Touchable.tsx +19 -20
  31. package/Components/Focusable/index.android.tsx +10 -3
  32. package/Components/FocusableCell/index.tsx +1 -1
  33. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  34. package/Components/FocusableGroup/index.tsx +0 -3
  35. package/Components/FocusableList/index.tsx +26 -10
  36. package/Components/FocusableScrollView/index.tsx +43 -13
  37. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  38. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  39. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  40. package/Components/Layout/TV/ScreenContainer.tsx +8 -2
  41. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  42. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +2 -1
  43. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -2
  44. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +3 -2
  45. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  46. package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
  47. package/Components/Layout/TV/index.tsx +6 -20
  48. package/Components/Layout/TV/index.web.tsx +4 -1
  49. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  50. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  51. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  52. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
  53. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  54. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  55. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  56. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  57. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  58. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  59. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  60. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  61. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +4 -12
  62. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +0 -229
  63. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  64. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  65. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  66. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  67. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  68. package/Components/MasterCell/utils/index.ts +9 -135
  69. package/Components/ModalComponent/BottomSheetModalContent.tsx +45 -19
  70. package/Components/ModalComponent/Button/Item.tsx +6 -5
  71. package/Components/ModalComponent/Button/assets.ts +1 -1
  72. package/Components/ModalComponent/Button/index.tsx +30 -43
  73. package/Components/ModalComponent/Header/index.tsx +3 -3
  74. package/Components/ModalComponent/utils.ts +55 -7
  75. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  76. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  77. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  78. package/Components/OfflineHandler/utils/index.ts +1 -1
  79. package/Components/PlayerContainer/PlayerContainer.tsx +43 -21
  80. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  81. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  82. package/Components/PlayerImageBackground/index.tsx +1 -1
  83. package/Components/River/ComponentsMap/ComponentsMap.tsx +42 -65
  84. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  85. package/Components/River/RiverFooter.tsx +39 -9
  86. package/Components/River/RiverItem.tsx +39 -3
  87. package/Components/River/TV/index.tsx +6 -1
  88. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
  89. package/Components/River/__tests__/__snapshots__/river.test.js.snap +20 -82
  90. package/Components/River/__tests__/componentsMap.test.js +17 -5
  91. package/Components/River/__tests__/river.test.js +75 -40
  92. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -4
  93. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  94. package/Components/RouteManager/__tests__/testId.test.js +8 -6
  95. package/Components/Screen/TV/index.web.tsx +5 -6
  96. package/Components/Screen/hooks.ts +53 -0
  97. package/Components/Screen/index.tsx +16 -42
  98. package/Components/ScreenResolver/__tests__/screenResolver.test.js +91 -70
  99. package/Components/Tabs/Tab.tsx +11 -9
  100. package/Components/TextInputTv/index.tsx +4 -3
  101. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  102. package/Components/TrackedView/index.tsx +1 -0
  103. package/Components/Transitioner/AnimationManager.js +15 -15
  104. package/Components/Transitioner/Scene.tsx +53 -24
  105. package/Components/Transitioner/Transitioner.tsx +3 -3
  106. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  107. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +9 -49
  108. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
  109. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  110. package/Components/Transitioner/index.js +8 -4
  111. package/Components/VideoLive/LiveImageManager.ts +27 -1
  112. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  113. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +51 -1
  114. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -5
  115. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  116. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +51 -31
  117. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
  118. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +48 -22
  119. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +12 -6
  120. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  121. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  122. package/Components/VideoModal/ModalAnimation/index.ts +2 -0
  123. package/Components/VideoModal/ModalAnimation/utils.ts +38 -2
  124. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  125. package/Components/VideoModal/PlayerDetails.tsx +18 -10
  126. package/Components/VideoModal/PlayerWrapper.tsx +43 -39
  127. package/Components/VideoModal/VideoModal.tsx +17 -11
  128. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -1
  129. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  130. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +0 -90
  131. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  132. package/Components/VideoModal/hooks/index.ts +7 -0
  133. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  134. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  135. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  136. package/Components/VideoModal/utils.ts +4 -5
  137. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  138. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  139. package/Components/Viewport/__tests__/utils.test.js +5 -4
  140. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  141. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  142. package/Components/ZappUIComponent/index.tsx +4 -17
  143. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  144. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  145. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  146. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  147. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  148. package/Contexts/ScreenContext/index.tsx +6 -12
  149. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  150. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  151. package/Decorators/Navigator/index.tsx +1 -1
  152. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +18 -24
  153. package/Decorators/RiverResolver/index.tsx +6 -8
  154. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  155. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  156. package/Decorators/ZappPipesDataConnector/index.tsx +6 -2
  157. package/package.json +7 -11
  158. package/tsconfig.json +2 -3
  159. package/.babelrc +0 -8
  160. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  161. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  162. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  163. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  164. package/Components/Cell/CellStyles/colors.js +0 -40
  165. package/Components/Cell/CellStyles/index.js +0 -15
  166. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  167. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  168. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  169. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  170. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  171. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  172. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
@@ -1,14 +1,16 @@
1
1
  import React, { useEffect, useRef } from "react";
2
2
  import {
3
- StyleProp,
4
- ViewStyle,
5
3
  Animated,
6
- Easing,
7
4
  Dimensions,
5
+ Easing,
6
+ StyleProp,
7
+ ViewStyle,
8
+ StyleSheet,
8
9
  } from "react-native";
9
10
  import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
10
11
  import { ComponentsMap } from "@applicaster/zapp-react-native-ui-components/Components/River/ComponentsMap";
11
12
  import { useSafeAreaInsets } from "react-native-safe-area-context";
13
+ import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
12
14
 
13
15
  const { width: SCREEN_WIDTH } = Dimensions.get("screen");
14
16
 
@@ -21,9 +23,9 @@ type Props = {
21
23
  entry: ZappEntry;
22
24
  style: StyleProp<ViewStyle>;
23
25
  configuration: Configuration;
24
- isTabletLandscape: boolean;
26
+ isTabletLandscape?: boolean;
25
27
  isAudioPlayer?: boolean;
26
- isTablet: boolean;
28
+ isTablet?: boolean;
27
29
  };
28
30
 
29
31
  const containerStyle = ({
@@ -38,9 +40,9 @@ export const PlayerDetails = ({
38
40
  entry,
39
41
  style,
40
42
  configuration,
41
- isTabletLandscape,
43
+ isTabletLandscape = false,
42
44
  isAudioPlayer,
43
- isTablet,
45
+ isTablet = false,
44
46
  }: Props) => {
45
47
  const screenData = useTargetScreenData(entry);
46
48
  const insets = useSafeAreaInsets();
@@ -77,6 +79,10 @@ export const PlayerDetails = ({
77
79
  }
78
80
  }, [isAudioPlayer]);
79
81
 
82
+ if (isNilOrEmpty(screenData?.ui_components)) {
83
+ return null;
84
+ }
85
+
80
86
  return (
81
87
  <Animated.View
82
88
  style={[
@@ -90,17 +96,19 @@ export const PlayerDetails = ({
90
96
  {
91
97
  // workaround for avoid wrong text-height after going back to portrait rotation
92
98
  // we don't see this view in landscape mode, so we are able to use fixed width from portrait mode
93
- width: isTablet ? undefined : SCREEN_WIDTH,
99
+ width: isTablet
100
+ ? undefined
101
+ : (StyleSheet.flatten(style)?.width ?? SCREEN_WIDTH),
94
102
  },
95
103
  ]}
96
104
  >
97
- {screenData && (
105
+ {screenData ? (
98
106
  <ComponentsMap
99
107
  riverId={screenData.id}
100
108
  feed={screenData?.data?.source}
101
109
  riverComponents={screenData.ui_components}
102
110
  />
103
- )}
111
+ ) : null}
104
112
  </Animated.View>
105
113
  );
106
114
  };
@@ -10,7 +10,8 @@ import { Edge, SafeAreaView } from "react-native-safe-area-context";
10
10
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
11
11
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
12
12
  import { PlayerDetails } from "./PlayerDetails";
13
- import { playerDimesionsHack } from "./utils";
13
+ import { playerDimensionsHack } from "./utils";
14
+ import { useDelayedPlayerDetails } from "./hooks";
14
15
 
15
16
  import {
16
17
  AnimatedScrollModal,
@@ -99,6 +100,24 @@ const getEdges = (isTablet: boolean, isInlineModal: boolean) => {
99
100
  return ["top"];
100
101
  };
101
102
 
103
+ const isPercentage = (value: string | number): boolean => {
104
+ if (typeof value === "string") {
105
+ return value.includes("%");
106
+ }
107
+
108
+ return false;
109
+ };
110
+
111
+ const getPercentageOf = (percent: string, value: number) => {
112
+ const percentageValue = parseFloat(percent.replace("%", ""));
113
+
114
+ if (isNaN(percentageValue)) {
115
+ return value;
116
+ }
117
+
118
+ return (value * percentageValue) / 100;
119
+ };
120
+
102
121
  const getTabletWidth = (
103
122
  configuration: Configuration,
104
123
  dimensions: DimensionsT
@@ -107,46 +126,23 @@ const getTabletWidth = (
107
126
  configuration?.tablet_landscape_sidebar_width;
108
127
 
109
128
  const { width } = dimensions;
129
+ let widthValue = Number(width);
130
+
131
+ if (isPercentage(width)) {
132
+ widthValue = getPercentageOf(width.toString(), SCREEN_WIDTH);
133
+ }
110
134
 
111
135
  const sidebarWidth = Number(tablet_landscape_sidebar_width?.replace("%", ""));
112
136
 
113
137
  if (tablet_landscape_sidebar_width?.includes("%")) {
114
- return Number(width) * (1 - sidebarWidth / 100);
138
+ return widthValue * (1 - sidebarWidth / 100);
115
139
  }
116
140
 
117
141
  if (Number.isNaN(sidebarWidth)) {
118
- return Number(width) * 0.65;
119
- }
120
-
121
- return Number(width) - sidebarWidth;
122
- };
123
-
124
- const showDetails = (
125
- isMobile: boolean,
126
- docked: boolean,
127
- isInlineModal,
128
- pip
129
- ): boolean => {
130
- if (pip) {
131
- return false;
132
- }
133
-
134
- if (!isInlineModal) {
135
- return false;
136
- }
137
-
138
- // for mobile we always show details. Mounting of it very heavy operation.
139
- if (isMobile) {
140
- return true;
141
- }
142
-
143
- // workaround for tablets we need to mount/unmount in order to avoid PlayerDetails content dissappearing
144
- // FIXME - find out the reason of dissapearing of content
145
- if (docked) {
146
- return false;
142
+ return widthValue * 0.65;
147
143
  }
148
144
 
149
- return true;
145
+ return widthValue - sidebarWidth;
150
146
  };
151
147
 
152
148
  const PlayerWrapperComponent = (props: Props) => {
@@ -167,7 +163,15 @@ const PlayerWrapperComponent = (props: Props) => {
167
163
 
168
164
  const isInlineModal = inline && isModal;
169
165
 
170
- // const style = getStyles(baseStyle, !isTablet, isInlineModal, pip);
166
+ // Mounting the PlayerDetails component is a resource-intensive process.
167
+ // Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
168
+ // The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
169
+ // This helps to avoid blocking the rotation and any animations related to the rotation.
170
+ const isShowPlayerDetails = useDelayedPlayerDetails({
171
+ isInline: isInlineModal,
172
+ isDocked: docked,
173
+ isPip: pip,
174
+ });
171
175
 
172
176
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
173
177
 
@@ -203,8 +207,8 @@ const PlayerWrapperComponent = (props: Props) => {
203
207
  const WrapperView = React.useMemo(() => (isTV() ? View : SafeAreaView), []);
204
208
 
205
209
  const childrenStyles = React.useMemo(
206
- () => ({ ...playerDimensions, ...playerDimesionsHack }),
207
- [containerDimensions, playerDimesionsHack]
210
+ () => ({ ...playerDimensions, ...playerDimensionsHack }),
211
+ [containerDimensions, playerDimensionsHack]
208
212
  );
209
213
 
210
214
  return (
@@ -213,7 +217,7 @@ const PlayerWrapperComponent = (props: Props) => {
213
217
  style={[
214
218
  safeAreaStyles(configuration, isTablet),
215
219
  style,
216
- playerDimesionsHack,
220
+ playerDimensionsHack,
217
221
  ]}
218
222
  >
219
223
  <AnimationComponent
@@ -227,7 +231,7 @@ const PlayerWrapperComponent = (props: Props) => {
227
231
  defaultStyles.playerContainer,
228
232
  containerDimensions,
229
233
  containerStyle,
230
- playerDimesionsHack,
234
+ playerDimensionsHack,
231
235
  ]}
232
236
  >
233
237
  <AnimationComponent
@@ -246,7 +250,7 @@ const PlayerWrapperComponent = (props: Props) => {
246
250
  </View>
247
251
 
248
252
  <AnimatedScrollModal>
249
- {showDetails(!isTablet, docked, isInlineModal, pip) && (
253
+ {isShowPlayerDetails ? (
250
254
  <AnimationComponent
251
255
  animationType={ComponentAnimationType.componentFade}
252
256
  style={defaultStyles.flex}
@@ -259,7 +263,7 @@ const PlayerWrapperComponent = (props: Props) => {
259
263
  isTablet={isTablet}
260
264
  />
261
265
  </AnimationComponent>
262
- )}
266
+ ) : null}
263
267
  </AnimatedScrollModal>
264
268
  </AnimationComponent>
265
269
  </WrapperView>
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
- import * as R from "ramda";
3
- import { StyleSheet, View, StatusBar } from "react-native";
2
+ import { equals } from "ramda";
3
+ import { StyleSheet, StatusBar, View } from "react-native";
4
4
 
5
5
  import { HandlePlayable } from "@applicaster/zapp-react-native-ui-components/Components/HandlePlayable";
6
6
  import {
@@ -17,20 +17,26 @@ import {
17
17
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
18
18
 
19
19
  import { withModalNavigationContextProvider } from "../../Contexts/ModalNavigationContext";
20
- import { useModalSize } from "./hooks/useModalSize";
21
- import { useBackgroundColor } from "./hooks/useBackgroundColor";
22
- import { useInitialPlayerState } from "./hooks/useInitialPlayerState";
20
+ import {
21
+ useModalSize,
22
+ useBackgroundColor,
23
+ useInitialPlayerState,
24
+ } from "./hooks";
25
+
23
26
  import { APP_EVENTS } from "@applicaster/zapp-react-native-utils/appUtils/events";
24
- import { Spinner } from "../Spinner";
25
27
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
26
28
  import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
27
29
  import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
28
30
  import { requiresAuthentication } from "@applicaster/zapp-react-native-utils/configurationUtils";
29
31
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
30
32
  import { ScreenContextProvider } from "../../Contexts/ScreenContext";
33
+ import { Spinner } from "../Spinner";
34
+ import { OpaqueLayer } from "./OpaqueLayer";
31
35
 
32
36
  import { AnimatedPlayerModalWrapper } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
33
37
 
38
+ const LOADER_BACKGROUND_COLOR = "rgba(64,64,64,0.5)";
39
+
34
40
  const styles = StyleSheet.create({
35
41
  container: {
36
42
  top: 0,
@@ -39,7 +45,6 @@ const styles = StyleSheet.create({
39
45
  bottom: 0,
40
46
  position: "absolute",
41
47
  },
42
- // eslint-disable-next-line react-native/no-color-literals
43
48
  loaderContainer: {
44
49
  top: 0,
45
50
  left: 0,
@@ -48,7 +53,7 @@ const styles = StyleSheet.create({
48
53
  position: "absolute",
49
54
  alignItems: "center",
50
55
  justifyContent: "center",
51
- backgroundColor: "rgba(64,64,64,.5)",
56
+ backgroundColor: LOADER_BACKGROUND_COLOR,
52
57
  },
53
58
  });
54
59
 
@@ -100,7 +105,7 @@ const VideoModalComponent = () => {
100
105
 
101
106
  const onHooksSuccess = ({ payload }) => {
102
107
  // set new modified entry
103
- if (!R.equals(payload, item)) {
108
+ if (!equals(payload, item)) {
104
109
  onVideoModalHookSuccessAnalyticsEvent();
105
110
  setVideoModalItem(payload);
106
111
  }
@@ -136,6 +141,9 @@ const VideoModalComponent = () => {
136
141
 
137
142
  <PathnameContext.Provider value={pathname}>
138
143
  <ScreenContextProvider pathname={pathname}>
144
+ {/* Hide content underneath when we switch to next video in fullscreen mode */}
145
+ {mode === "FULLSCREEN" && <OpaqueLayer />}
146
+
139
147
  {itemIdHooksFinished === item?.id ? (
140
148
  <AnimatedPlayerModalWrapper
141
149
  style={[
@@ -148,8 +156,6 @@ const VideoModalComponent = () => {
148
156
  <HandlePlayable
149
157
  item={item}
150
158
  isModal={mode !== "PIP"}
151
- modalHeight={modalSize.height}
152
- modalWidth={modalSize.width}
153
159
  mode={mode}
154
160
  />
155
161
  </AnimatedPlayerModalWrapper>
@@ -62,7 +62,7 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
62
62
  })),
63
63
  }));
64
64
 
65
- jest.mock("../utils", () => ({ playerDimesionsHack: {} }));
65
+ jest.mock("../utils", () => ({ playerDimensionsHack: {} }));
66
66
 
67
67
  const { PlayerWrapper } = require("../PlayerWrapper");
68
68
 
@@ -1,43 +1,5 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`PlayerDetails renders properly 1`] = `
4
- <View
5
- collapsable={false}
6
- style={
7
- {
8
- "backgroundColor": "transparent",
9
- "flex": 1,
10
- "marginTop": -8,
11
- "paddingTop": -8,
12
- "width": 750,
13
- }
14
- }
15
- >
16
- <View
17
- feed="test-source"
18
- riverComponents={[]}
19
- riverId="test-id"
20
- />
21
- </View>
22
- `;
3
+ exports[`PlayerDetails renders properly 1`] = `null`;
23
4
 
24
- exports[`PlayerDetails renders properly on tablet in landscape orientation 1`] = `
25
- <View
26
- collapsable={false}
27
- style={
28
- {
29
- "backgroundColor": "transparent",
30
- "flex": 1,
31
- "marginTop": -20,
32
- "paddingTop": 40,
33
- "width": 750,
34
- }
35
- }
36
- >
37
- <View
38
- feed="test-source"
39
- riverComponents={[]}
40
- riverId="test-id"
41
- />
42
- </View>
43
- `;
5
+ exports[`PlayerDetails renders properly on tablet in landscape orientation 1`] = `null`;
@@ -71,36 +71,6 @@ exports[`PlayerWrapper renders inline 1`] = `
71
71
  }
72
72
  testID="test-player-container"
73
73
  />
74
- <View
75
- animationType="componentFade"
76
- style={
77
- {
78
- "flex": 1,
79
- }
80
- }
81
- >
82
- <View
83
- configuration={
84
- {
85
- "tablet_landscape_player_container_background_color": "red",
86
- "tablet_landscape_sidebar_width": "35%",
87
- }
88
- }
89
- entry={
90
- {
91
- "id": "test",
92
- }
93
- }
94
- isTablet={false}
95
- isTabletLandscape={false}
96
- style={
97
- {
98
- "flex": 1,
99
- "paddingTop": 20,
100
- }
101
- }
102
- />
103
- </View>
104
74
  </View>
105
75
  </RNCSafeAreaView>
106
76
  </RNCSafeAreaProvider>
@@ -177,36 +147,6 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
177
147
  }
178
148
  testID="test-player-container"
179
149
  />
180
- <View
181
- animationType="componentFade"
182
- style={
183
- {
184
- "flex": 1,
185
- }
186
- }
187
- >
188
- <View
189
- configuration={
190
- {
191
- "tablet_landscape_player_container_background_color": "red",
192
- "tablet_landscape_sidebar_width": "35%",
193
- }
194
- }
195
- entry={
196
- {
197
- "id": "test",
198
- }
199
- }
200
- isTablet={false}
201
- isTabletLandscape={false}
202
- style={
203
- {
204
- "flex": 1,
205
- "paddingTop": 20,
206
- }
207
- }
208
- />
209
- </View>
210
150
  </View>
211
151
  </RNCSafeAreaView>
212
152
  </RNCSafeAreaProvider>
@@ -299,36 +239,6 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
299
239
  }
300
240
  />
301
241
  </View>
302
- <View
303
- animationType="componentFade"
304
- style={
305
- {
306
- "flex": 1,
307
- }
308
- }
309
- >
310
- <View
311
- configuration={
312
- {
313
- "tablet_landscape_player_container_background_color": "red",
314
- "tablet_landscape_sidebar_width": "35%",
315
- }
316
- }
317
- entry={
318
- {
319
- "id": "test",
320
- }
321
- }
322
- isTablet={true}
323
- isTabletLandscape={true}
324
- style={
325
- {
326
- "flex": 1,
327
- "paddingTop": 20,
328
- }
329
- }
330
- />
331
- </View>
332
242
  </View>
333
243
  </RNCSafeAreaView>
334
244
  </RNCSafeAreaProvider>
@@ -0,0 +1,89 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+ import { useDelayedPlayerDetails } from "../useDelayedPlayerDetails";
3
+ import { withTimeout$ } from "@applicaster/zapp-react-native-utils/idleUtils";
4
+ import { showDetails } from "../utils";
5
+ import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
6
+
7
+ jest.mock("@applicaster/zapp-react-native-utils/idleUtils", () => ({
8
+ withTimeout$: jest.fn(),
9
+ }));
10
+
11
+ jest.mock("../utils", () => ({
12
+ showDetails: jest.fn(),
13
+ }));
14
+
15
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
16
+ useIsTablet: jest.fn(),
17
+ }));
18
+
19
+ describe("useDelayedPlayerDetails", () => {
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+ });
23
+
24
+ it("should return false initially", () => {
25
+ (withTimeout$ as jest.Mock).mockReturnValue({
26
+ subscribe: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }),
27
+ });
28
+
29
+ const { result } = renderHook(() =>
30
+ useDelayedPlayerDetails({ isInline: true, isDocked: false, isPip: false })
31
+ );
32
+
33
+ expect(result.current).toBe(false);
34
+ });
35
+
36
+ it("should return true if showDetails returns true", () => {
37
+ (withTimeout$ as jest.Mock).mockReturnValue({
38
+ subscribe: (callback) => {
39
+ callback.next();
40
+
41
+ return { unsubscribe: jest.fn() };
42
+ },
43
+ });
44
+
45
+ (showDetails as jest.Mock).mockReturnValue(true);
46
+ (useIsTablet as jest.Mock).mockReturnValue(false);
47
+
48
+ const { result } = renderHook(() =>
49
+ useDelayedPlayerDetails({ isInline: true, isDocked: false, isPip: false })
50
+ );
51
+
52
+ expect(result.current).toBe(true);
53
+ });
54
+
55
+ it("should return false if showDetails returns false", () => {
56
+ (withTimeout$ as jest.Mock).mockReturnValue({
57
+ subscribe: (callback) => {
58
+ callback.next();
59
+
60
+ return { unsubscribe: jest.fn() };
61
+ },
62
+ });
63
+
64
+ (showDetails as jest.Mock).mockReturnValue(false);
65
+ (useIsTablet as jest.Mock).mockReturnValue(false);
66
+
67
+ const { result } = renderHook(() =>
68
+ useDelayedPlayerDetails({ isInline: true, isDocked: false, isPip: false })
69
+ );
70
+
71
+ expect(result.current).toBe(false);
72
+ });
73
+
74
+ it("should unsubscribe on unmount", () => {
75
+ const unsubscribeMock = jest.fn();
76
+
77
+ (withTimeout$ as jest.Mock).mockReturnValue({
78
+ subscribe: jest.fn().mockReturnValue({ unsubscribe: unsubscribeMock }),
79
+ });
80
+
81
+ const { unmount } = renderHook(() =>
82
+ useDelayedPlayerDetails({ isInline: true, isDocked: false, isPip: false })
83
+ );
84
+
85
+ unmount();
86
+
87
+ expect(unsubscribeMock).toHaveBeenCalled();
88
+ });
89
+ });
@@ -0,0 +1,7 @@
1
+ export { useBackgroundColor } from "./useBackgroundColor";
2
+
3
+ export { useDelayedPlayerDetails } from "./useDelayedPlayerDetails";
4
+
5
+ export { useInitialPlayerState } from "./useInitialPlayerState";
6
+
7
+ export { useModalSize } from "./useModalSize";
@@ -0,0 +1,49 @@
1
+ import * as React from "react";
2
+ import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
3
+ import { withTimeout$ } from "@applicaster/zapp-react-native-utils/idleUtils";
4
+
5
+ import { showDetails } from "./utils";
6
+
7
+ const TIMEOUT = 100; // ms
8
+
9
+ type Props = { isInline: boolean; isDocked: boolean; isPip: boolean };
10
+
11
+ /**
12
+ * Custom hook to determine whether to show player details with a delay.
13
+ *
14
+ * @param {Object} params - The parameters object.
15
+ * @param {boolean} params.isInline - Indicates if the player is inline.
16
+ * @param {boolean} params.isDocked - Indicates if the player is docked.
17
+ * @param {boolean} params.isPip - Indicates if the player is in PIP mode.
18
+ * @returns {boolean} - Returns true if player details should be shown, otherwise false.
19
+ */
20
+ export const useDelayedPlayerDetails = ({
21
+ isInline,
22
+ isDocked,
23
+ isPip,
24
+ }: Props): boolean => {
25
+ const [shouldShowDetails, setShouldShowDetails] = React.useState(false);
26
+
27
+ const isTablet = useIsTablet();
28
+
29
+ React.useEffect(() => {
30
+ const subscription = withTimeout$(TIMEOUT).subscribe({
31
+ next: () => {
32
+ setShouldShowDetails(() => {
33
+ return showDetails({
34
+ isMobile: !isTablet,
35
+ isInline,
36
+ isDocked,
37
+ isPip,
38
+ });
39
+ });
40
+ },
41
+ });
42
+
43
+ return () => {
44
+ subscription.unsubscribe();
45
+ };
46
+ }, [isDocked, isTablet, isInline, isPip]);
47
+
48
+ return shouldShowDetails;
49
+ };