@applicaster/zapp-react-native-ui-components 13.0.0-rc.14 → 13.0.0-rc.140

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 (226) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
  3. package/Components/AudioPlayer/index.tsx +15 -0
  4. package/Components/AudioPlayer/mobile/Layout.tsx +63 -0
  5. package/Components/AudioPlayer/mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap +66 -0
  6. package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
  7. package/Components/AudioPlayer/mobile/index.tsx +23 -0
  8. package/Components/AudioPlayer/tv/Artwork.tsx +40 -0
  9. package/Components/AudioPlayer/{AudioPlayerLayout.tsx → tv/Layout.tsx} +37 -79
  10. package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +2 -1
  11. package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +12 -9
  12. package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +12 -9
  13. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +5 -8
  14. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +6 -6
  15. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +11 -6
  16. package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +170 -0
  17. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/channel.test.js.snap +3 -3
  18. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +3 -3
  19. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +3 -3
  20. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +3 -5
  21. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +5 -7
  22. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +3 -5
  23. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +3 -5
  24. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +3 -5
  25. package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +3 -5
  26. package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +21 -62
  27. package/Components/AudioPlayer/types.ts +40 -0
  28. package/Components/BaseFocusable/index.ios.ts +1 -1
  29. package/Components/BaseFocusable/index.tsx +67 -31
  30. package/Components/Cell/Cell.tsx +14 -14
  31. package/Components/Cell/CellWithFocusable.tsx +50 -59
  32. package/Components/Cell/CellWrapper.tsx +18 -0
  33. package/Components/Cell/TvOSCellComponent.tsx +20 -26
  34. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  35. package/Components/Cell/index.js +3 -1
  36. package/Components/Cell/styles.ts +17 -0
  37. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +50 -50
  38. package/Components/CellRendererResolver/index.ts +2 -1
  39. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  40. package/Components/ComponentResolver/__tests__/componentResolver.test.js +26 -30
  41. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  42. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  43. package/Components/ErrorScreen/index.tsx +14 -6
  44. package/Components/Focusable/Focusable.tsx +1 -54
  45. package/Components/Focusable/FocusableTvOS.tsx +6 -2
  46. package/Components/Focusable/Touchable.tsx +19 -20
  47. package/Components/Focusable/index.android.tsx +10 -3
  48. package/Components/FocusableCell/index.tsx +1 -1
  49. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  50. package/Components/FocusableGroup/index.tsx +0 -3
  51. package/Components/FocusableList/index.tsx +26 -10
  52. package/Components/FocusableScrollView/index.tsx +43 -13
  53. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  54. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
  55. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +5 -3
  56. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  57. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  58. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  59. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  60. package/Components/Layout/TV/ScreenContainer.tsx +8 -2
  61. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  62. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +3 -1
  63. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  64. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +6 -5
  65. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +12 -11
  66. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  67. package/Components/Layout/TV/__tests__/index.test.tsx +14 -4
  68. package/Components/Layout/TV/index.tsx +6 -20
  69. package/Components/Layout/TV/index.web.tsx +4 -1
  70. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  71. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  72. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  73. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
  74. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  75. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  76. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  77. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  78. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  79. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  80. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  81. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  82. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  83. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  84. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  85. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +11 -19
  86. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +6 -235
  87. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  88. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  89. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  90. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  91. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  92. package/Components/MasterCell/utils/index.ts +9 -135
  93. package/Components/ModalComponent/BottomSheetModalContent.tsx +66 -54
  94. package/Components/ModalComponent/Button/Item.tsx +6 -5
  95. package/Components/ModalComponent/Button/assets.ts +1 -1
  96. package/Components/ModalComponent/Button/index.tsx +45 -62
  97. package/Components/ModalComponent/Header/index.tsx +12 -11
  98. package/Components/ModalComponent/utils.ts +55 -7
  99. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  100. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  101. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  102. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  103. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  104. package/Components/OfflineHandler/utils/index.ts +1 -1
  105. package/Components/PlayerContainer/PlayerContainer.tsx +76 -66
  106. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  107. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  108. package/Components/PlayerImageBackground/index.tsx +2 -2
  109. package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -68
  110. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  111. package/Components/River/RefreshControl.tsx +1 -1
  112. package/Components/River/RiverFooter.tsx +39 -9
  113. package/Components/River/RiverItem.tsx +44 -4
  114. package/Components/River/TV/index.tsx +6 -1
  115. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +115 -46
  116. package/Components/River/__tests__/__snapshots__/river.test.js.snap +21 -83
  117. package/Components/River/__tests__/componentsMap.test.js +64 -17
  118. package/Components/River/__tests__/river.test.js +75 -40
  119. package/Components/RouteManager/TestId.tsx +1 -5
  120. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -5
  121. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  122. package/Components/RouteManager/__tests__/testId.test.js +4 -6
  123. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  124. package/Components/Screen/TV/index.web.tsx +5 -6
  125. package/Components/Screen/__tests__/Screen.test.tsx +53 -31
  126. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +6 -6
  127. package/Components/Screen/hooks.ts +53 -0
  128. package/Components/Screen/index.tsx +16 -42
  129. package/Components/ScreenResolver/__tests__/screenResolver.test.js +95 -70
  130. package/Components/Tabs/Tab.tsx +12 -9
  131. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  132. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  133. package/Components/TextInputTv/index.tsx +6 -5
  134. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  135. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  136. package/Components/TrackedView/index.tsx +1 -0
  137. package/Components/Transitioner/AnimationManager.js +15 -15
  138. package/Components/Transitioner/Scene.tsx +53 -24
  139. package/Components/Transitioner/Transitioner.tsx +3 -3
  140. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  141. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  142. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +10 -50
  143. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  144. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  145. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  146. package/Components/Transitioner/index.js +8 -4
  147. package/Components/VideoLive/LiveImageManager.ts +27 -1
  148. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  149. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  150. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +6 -10
  151. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  152. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +51 -31
  153. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
  154. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +48 -23
  155. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +16 -15
  156. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  157. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  158. package/Components/VideoModal/ModalAnimation/index.ts +4 -1
  159. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  160. package/Components/VideoModal/ModalAnimation/utils.ts +32 -2
  161. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  162. package/Components/VideoModal/PlayerDetails.tsx +18 -10
  163. package/Components/VideoModal/PlayerWrapper.tsx +51 -57
  164. package/Components/VideoModal/VideoModal.tsx +17 -11
  165. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  166. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  167. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  168. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +74 -104
  169. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +51 -0
  170. package/Components/VideoModal/hooks/index.ts +7 -0
  171. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +38 -0
  172. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  173. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  174. package/Components/VideoModal/utils.ts +6 -9
  175. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  176. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  177. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  178. package/Components/Viewport/__tests__/utils.test.js +5 -4
  179. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  180. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  181. package/Components/ZappUIComponent/index.tsx +4 -17
  182. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  183. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  184. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  185. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  186. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  187. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  188. package/Contexts/ScreenContext/index.tsx +6 -12
  189. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  190. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  191. package/Decorators/Navigator/index.tsx +1 -1
  192. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  193. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  194. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  195. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  196. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  197. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  198. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  199. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +27 -27
  200. package/Decorators/RiverResolver/index.tsx +6 -8
  201. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  202. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  203. package/Decorators/ZappPipesDataConnector/index.tsx +7 -3
  204. package/package.json +13 -11
  205. package/tsconfig.json +2 -3
  206. package/.babelrc +0 -8
  207. package/Components/AudioPlayer/Artwork.tsx +0 -35
  208. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +0 -123
  209. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -50
  210. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -27
  211. package/Components/AudioPlayer/index.ts +0 -1
  212. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  213. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  214. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  215. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  216. package/Components/Cell/CellStyles/colors.js +0 -40
  217. package/Components/Cell/CellStyles/index.js +0 -15
  218. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  219. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  220. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  221. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  222. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  223. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  224. package/Decorators/RiverFeedLoader/utils.ts +0 -100
  225. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
  226. /package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +0 -0
@@ -1,17 +1,30 @@
1
1
  import * as React from "react";
2
2
  import { FocusableGroupNative } from "@applicaster/zapp-react-native-ui-components/Components/NativeFocusables";
3
3
  import { BaseFocusable } from "@applicaster/zapp-react-native-ui-components/Components/BaseFocusable";
4
-
5
- function noop() {}
4
+ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
5
+
6
+ const { log_verbose } = createLogger({
7
+ subsystem: "General",
8
+ category: "FocusableGroup",
9
+ });
10
+
11
+ type FocusableGroupNativeEvent = {
12
+ nativeEvent: {
13
+ focusHeading: FocusManager.Direction;
14
+ groupId: string;
15
+ isActive: boolean;
16
+ isFocusDisabled: boolean;
17
+ isFocusingByUser: boolean;
18
+ itemId: string;
19
+ target: number;
20
+ };
21
+ };
6
22
 
7
23
  type Props = {
8
24
  id: string;
9
25
  children: (arg1: boolean) => React.ComponentType<any>;
10
- onWillUpdateFocus: (nativeEvent: any) => void;
11
- onDidUpdateFocus: (nativeEvent: any) => void;
12
26
  isFocusDisabled: boolean;
13
- initialItemId: string;
14
- resetFocusToInitialValue: boolean;
27
+ isWithMemory: boolean;
15
28
  focusGroupRef: React.Component;
16
29
  shouldUsePreferredFocus: boolean;
17
30
  groupId: string;
@@ -21,86 +34,26 @@ type Props = {
21
34
  };
22
35
 
23
36
  export class FocusableGroup extends BaseFocusable<Props> {
24
- focusableGroupNativeRef: React.Component | null;
25
- constructor(props) {
26
- super(props);
27
- this.focusableGroupNativeRef = null;
28
-
29
- this.state = {
30
- isActive: false,
31
- };
32
-
33
- this.onWillUpdateFocus = this.onWillUpdateFocus.bind(this);
34
- this.onDidUpdateFocus = this.onDidUpdateFocus.bind(this);
35
- this.isGroup = true;
36
-
37
- this.shouldUsePreferredFocus = this.shouldUsePreferredFocus.bind(this);
38
- this.measureView = this.measureView.bind(this);
39
- }
40
-
41
- connectedScreenId() {
42
- const {
43
- screenData: { screenId, parentScreenId },
44
- } = this.props;
45
-
46
- if (screenId) {
47
- return null;
48
- }
49
-
50
- return parentScreenId ? `${parentScreenId}-${screenId}` : screenId;
51
- }
52
-
53
- /**
54
- * tells whether the group should give focus to a preferred item when it gains focus from another
55
- * group
56
- * @returns {boolean}
57
- */
58
- shouldUsePreferredFocus() {
59
- return this.props.shouldUsePreferredFocus || false;
60
- }
61
-
62
- /**
63
- * indicates whether the underlying component should claim preferred focus
64
- * when navigating into the group of this item
65
- * @returns {boolean}
66
- */
67
- isPreferredFocus() {
68
- return this.props.preferredFocus || false;
69
- }
70
-
71
- onWillUpdateFocus({ nativeEvent }) {
72
- const { isActive } = nativeEvent;
73
- this.setState({ isActive });
74
- const { onWillUpdateFocus = noop } = this.props;
75
- onWillUpdateFocus(nativeEvent);
76
- }
77
-
78
- onDidUpdateFocus({ nativeEvent }) {
79
- const { onDidUpdateFocus = noop } = this.props;
80
- onDidUpdateFocus(nativeEvent);
81
- }
82
-
83
- setFocusDisabled(isFocusDisabled) {
84
- if (this.ref) {
85
- this.ref.current.setNativeProps({
86
- isFocusDisabled,
87
- });
88
- }
89
- }
90
-
91
37
  render() {
92
38
  const {
93
39
  children,
94
40
  id,
95
41
  isFocusDisabled,
96
- initialItemId,
97
- resetFocusToInitialValue,
98
- style,
42
+ isWithMemory,
43
+ style = {},
99
44
  groupId,
100
45
  ...otherProps
101
46
  } = this.props;
102
47
 
103
- const focusableStyles = style || {};
48
+ const onGroupFocus = ({ nativeEvent }: FocusableGroupNativeEvent) => {
49
+ log_verbose("FOCUSABLE_GROUP: onGroupFocus", { nativeEvent });
50
+ this.onFocus(this.ref, nativeEvent.focusHeading);
51
+ };
52
+
53
+ const onGroupBlur = ({ nativeEvent }: FocusableGroupNativeEvent) => {
54
+ log_verbose("FOCUSABLE_GROUP: onGroupBlur", { nativeEvent });
55
+ this.onBlur(this.ref, nativeEvent.focusHeading);
56
+ };
104
57
 
105
58
  return (
106
59
  <FocusableGroupNative
@@ -108,16 +61,11 @@ export class FocusableGroup extends BaseFocusable<Props> {
108
61
  itemId={id}
109
62
  ref={this.ref}
110
63
  isFocusDisabled={isFocusDisabled}
111
- initialItemId={initialItemId}
112
- resetFocusToInitialValue={resetFocusToInitialValue}
113
- onLayout={this.measureView}
114
- onViewFocus={this.onFocus}
115
- onViewPress={this.onPress}
116
- onViewBlur={this.onBlur}
117
- style={focusableStyles}
64
+ isWithMemory={isWithMemory}
65
+ onGroupFocus={onGroupFocus}
66
+ onGroupBlur={onGroupBlur}
67
+ style={style}
118
68
  {...otherProps}
119
- onWillUpdateFocus={this.onWillUpdateFocus}
120
- onDidUpdateFocus={this.onDidUpdateFocus}
121
69
  >
122
70
  {children}
123
71
  </FocusableGroupNative>
@@ -16,12 +16,9 @@ type Props = {
16
16
  prioritiseFocusOn?: number;
17
17
  groupId?: string;
18
18
  hasTVPreferredFocus?: boolean;
19
- resetFocusToInitialValue?: boolean;
20
19
  onFocus?: () => void;
21
20
  onBlur?: () => void;
22
- onWillUpdateFocus?: (event?: any) => void;
23
21
  willReceiveFocus?: (event?: any) => void;
24
- onDidUpdateFocus?: (event?: any) => void;
25
22
  hasLostFocus?: any;
26
23
  nextFocusUp?: any;
27
24
  nextFocusDown?: any;
@@ -15,6 +15,7 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
15
15
 
16
16
  import { useParentFocus, useCheckItemIdsForUnique } from "./hooks";
17
17
  import { FocusableListItemWrapper } from "./FocusableListItemWrapper";
18
+ import { FocusableScrollView } from "../FocusableScrollView";
18
19
 
19
20
  const mapIndexed = R.addIndex(R.map);
20
21
 
@@ -54,6 +55,7 @@ export type Props<ItemT> = FlatListProps<ItemT> & {
54
55
  disableNextFocusUp?: boolean;
55
56
  disableNextFocusLeft?: boolean;
56
57
  disableNextFocusRight?: boolean;
58
+ useScrollView?: boolean;
57
59
  } & ParentFocus;
58
60
 
59
61
  function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
@@ -87,8 +89,8 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
87
89
  initialFocusDirection = "down",
88
90
  data = [],
89
91
  // eslint-disable-next-line unused-imports/no-unused-vars
90
- onAllComponentsLoaded, // TODO: re-implement it
91
92
  omitPropsPropagation = [],
93
+ useScrollView = false,
92
94
  } = props;
93
95
 
94
96
  useCheckItemIdsForUnique({ componentId: props.id, items: data });
@@ -274,6 +276,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
274
276
  "initialFocusDirection",
275
277
  "withStateMemory",
276
278
  "useSequentialLoading",
279
+ "useScrollView",
277
280
  ...omitPropsPropagation,
278
281
  ],
279
282
  R.__
@@ -296,15 +299,28 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
296
299
  return (
297
300
  // @ts-ignore
298
301
  <ChildrenFocusDeactivatorView flex={1}>
299
- <FlatList
300
- focusable={false}
301
- scrollEnabled={false}
302
- ref={ref}
303
- {...getFlatListProps(props)}
304
- renderItem={renderItem}
305
- onEndReached={onEndReached}
306
- initialNumToRender={initialNumToRender}
307
- />
302
+ {useScrollView ? (
303
+ <FocusableScrollView
304
+ ref={ref}
305
+ {...getFlatListProps(props)}
306
+ onEndReached={onEndReached}
307
+ initialNumToRender={initialNumToRender}
308
+ renderItem={renderItem}
309
+ focused={focused}
310
+ data={data}
311
+ />
312
+ ) : (
313
+ <FlatList
314
+ testID="focusable-list-flat-list"
315
+ focusable={false}
316
+ scrollEnabled={false}
317
+ ref={ref}
318
+ {...getFlatListProps(props)}
319
+ renderItem={renderItem}
320
+ onEndReached={onEndReached}
321
+ initialNumToRender={initialNumToRender}
322
+ />
323
+ )}
308
324
  </ChildrenFocusDeactivatorView>
309
325
  );
310
326
  }
@@ -11,6 +11,13 @@ import {
11
11
  useInitialFocus,
12
12
  } from "@applicaster/zapp-react-native-utils/focusManager";
13
13
 
14
+ export type FocusableScrollViewRenderItem = (info: {
15
+ item: ZappUIComponent;
16
+ index: number;
17
+ focused: boolean;
18
+ parentFocus: ParentFocus;
19
+ }) => React.ReactElement;
20
+
14
21
  export type Props = ScrollViewProps & {
15
22
  id?: number | string;
16
23
  horizontal?: boolean;
@@ -32,17 +39,27 @@ export type Props = ScrollViewProps & {
32
39
  initialFocusDirection?: FocusManager.Android.FocusNavigationDirections;
33
40
  onAllComponentsLoaded?: () => void;
34
41
  omitPropsPropagation?: Array<keyof FlatListProps<any>>;
35
- renderItem: (info: {
36
- item: ZappUIComponent;
37
- index: number;
38
- focused: boolean;
39
- parentFocus: ParentFocus;
40
- }) => React.ReactElement;
42
+ renderItem: FocusableScrollViewRenderItem;
41
43
  } & ParentFocus;
42
44
 
43
45
  type State = boolean[];
44
46
  type Action = { index?: number; isFocusable: boolean; type?: string };
45
47
 
48
+ const unwrapArray = (maybeArray) =>
49
+ Array.isArray(maybeArray) ? maybeArray[0] : maybeArray;
50
+
51
+ const getEntry = <T extends unknown>(data: T | T[], index: unknown): T => {
52
+ let entry;
53
+
54
+ if (R.isNil(index)) {
55
+ entry = unwrapArray(data);
56
+ } else if (typeof index === "number") {
57
+ entry = unwrapArray(data[index]);
58
+ }
59
+
60
+ return entry;
61
+ };
62
+
46
63
  const focusableStateReducer = (
47
64
  state: State,
48
65
  { index = null, isFocusable, type = null }: Action
@@ -73,7 +90,7 @@ const extendScrollViewRef = (_ref, childCompsMeasurementsMap) => {
73
90
  };
74
91
 
75
92
  _ref.scrollToIndex = (params) => {
76
- const { index, viewOffset } = params;
93
+ const { index, viewOffset = 0 } = params;
77
94
 
78
95
  const itemByIndex = R.find(R.propEq("index", index))(
79
96
  R.values(childCompsMeasurementsMap)
@@ -129,8 +146,11 @@ function FocusableScrollViewComponent(props: Props, ref) {
129
146
  );
130
147
 
131
148
  const getFocusableEntryId = React.useCallback(
132
- (_entry: ZappEntry, index?: number) => {
133
- const entry = R.isNil(index) ? _entry : data[index];
149
+ (_entry: ZappEntry | null, index?: number) => {
150
+ const entry: { id?: string } = getEntry(
151
+ R.isNil(index) ? _entry : data,
152
+ index
153
+ );
134
154
 
135
155
  return entry ? `${props.id}--${entry?.id}` : undefined;
136
156
  },
@@ -273,16 +293,25 @@ function FocusableScrollViewComponent(props: Props, ref) {
273
293
  const renderItem = React.useCallback(
274
294
  (item, index) => {
275
295
  const renderArgs = { item, index };
276
- const id = `${props.id}--${renderArgs?.item?.id}`;
277
- const nextFocus = getNextFocus(renderArgs?.index);
296
+
297
+ const id = getFocusableEntryId(
298
+ Array.isArray(item) ? item[0] : item,
299
+ index
300
+ );
301
+
302
+ const nextFocus = getNextFocus(index);
278
303
 
279
304
  const onItemLayout = (event) => {
280
- childCompsMeasurementsMap.current[item.id] = {
305
+ childCompsMeasurementsMap.current[
306
+ Array.isArray(item) ? index : item.id
307
+ ] = {
281
308
  index,
282
309
  layout: event.nativeEvent.layout,
283
310
  };
284
311
  };
285
312
 
313
+ const onSetIsFocusable = setIsFocusable(renderArgs.index);
314
+
286
315
  return (
287
316
  <View key={id} onLayout={onItemLayout}>
288
317
  <Focusable
@@ -305,6 +334,7 @@ function FocusableScrollViewComponent(props: Props, ref) {
305
334
  id={id}
306
335
  disableFocus={shouldDisableFocus(renderArgs?.index)}
307
336
  blockFocus={!isRendered(renderArgs?.index)}
337
+ onSetIsFocusable={onSetIsFocusable}
308
338
  {...focusableItemProps}
309
339
  >
310
340
  {(focused, parentFocus, parentRef) => (
@@ -319,7 +349,7 @@ function FocusableScrollViewComponent(props: Props, ref) {
319
349
  isReadyToRender={isReadyToRender}
320
350
  onLoadFinished={onLoadFinished(renderArgs.index)}
321
351
  onLoadFailed={onLoadFailed(renderArgs.index)}
322
- setIsFocusable={setIsFocusable(renderArgs.index)}
352
+ setIsFocusable={onSetIsFocusable}
323
353
  />
324
354
  )}
325
355
  </Focusable>
@@ -11,6 +11,7 @@ import { allSettled } from "promise";
11
11
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
12
12
  import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
13
13
  import { ScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext";
14
+ import { useEventAlerts } from "./utils/useEventAlerts";
14
15
 
15
16
  const { log_info } = createLogger({
16
17
  category: "ScreenContainer",
@@ -103,6 +104,8 @@ export const GeneralContentScreen = ({
103
104
  [typeof cellTapAction === "function" ? cellTapAction : onCellTapAction]
104
105
  );
105
106
 
107
+ useEventAlerts(screenData);
108
+
106
109
  if (!isReady || isNilOrEmpty(components || uiComponents)) return null;
107
110
 
108
111
  return (
@@ -16,6 +16,15 @@ import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Co
16
16
  import { Provider } from "react-redux";
17
17
  import configureStore from "redux-mock-store";
18
18
 
19
+ jest.mock(
20
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute",
21
+ () => ({
22
+ useRoute: jest.fn().mockReturnValue({
23
+ pathname: "/home",
24
+ }),
25
+ })
26
+ );
27
+
19
28
  const homeStack = {
20
29
  route: "/home",
21
30
  state: {
@@ -3,13 +3,15 @@ import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
3
3
  import { useEffect, useMemo } from "react";
4
4
  import { useDispatch } from "react-redux";
5
5
 
6
- import { useLayoutPresets } from "@applicaster/zapp-react-native-redux/hooks/useLayoutPresets";
7
- import { useZappPipesFeeds } from "@applicaster/zapp-react-native-redux/hooks/useZappPipesFeeds";
6
+ import {
7
+ useLayoutPresets,
8
+ useZappPipesFeeds,
9
+ } from "@applicaster/zapp-react-native-redux/hooks";
8
10
  import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
9
11
  import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
10
12
  import { Categories } from "./logger";
11
13
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
12
- import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
14
+ import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute";
13
15
  import {
14
16
  ZappPipesEntryContext,
15
17
  ZappPipesScreenContext,
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { showAlertDialog } from "@applicaster/zapp-react-native-utils/alertUtils";
3
+ import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "@applicaster/zapp-react-native-utils/actionsExecutor/consts";
4
+ import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
5
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
6
+ import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
7
+
8
+ export const useEventAlerts = (screenData: ZappRiver) => {
9
+ const localizations = useLocalizedStrings({
10
+ localizations: screenData?.localizations || {},
11
+ });
12
+
13
+ const isActive = useIsScreenActive();
14
+
15
+ const onMaxTagsReached = React.useCallback(() => {
16
+ // We can't skip subscribe hook call, so we have to check.
17
+ if (!isActive || !localizations?.msg_maximum_selection_reached_message) {
18
+ return;
19
+ }
20
+
21
+ showAlertDialog({
22
+ title: "",
23
+ message: localizations.msg_maximum_selection_reached_message,
24
+ okButtonText:
25
+ localizations.msg_maximum_selection_reached_message_ok_button || "OK",
26
+ });
27
+ }, [localizations, isActive]);
28
+
29
+ useSubscriberFor(TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT, onMaxTagsReached);
30
+ };
@@ -1,17 +1,18 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { ViewStyle } from "react-native";
4
3
  import {
5
4
  findPluginByType,
6
5
  findPluginByIdentifier,
7
6
  } from "@applicaster/zapp-react-native-utils/pluginUtils";
8
- import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
9
7
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
10
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
11
- import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
8
+ import {
9
+ useDimensions,
10
+ useNavigation,
11
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
12
12
 
13
13
  import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
14
14
  import { PlayerContainer } from "../PlayerContainer";
15
+ import { useModalSize } from "../VideoModal/hooks";
15
16
 
16
17
  type Props = {
17
18
  item: ZappEntry;
@@ -78,12 +79,6 @@ const getPlayer = (
78
79
  return getPlayerWithModuleProperties(PlayerModule);
79
80
  };
80
81
 
81
- const dimensionsContext: "window" | "screen" = platformSelect({
82
- android_tv: "window",
83
- amazon: "window",
84
- default: "screen",
85
- });
86
-
87
82
  type PlayableComponent = {
88
83
  Component: React.ComponentType<any>;
89
84
  };
@@ -91,16 +86,11 @@ type PlayableComponent = {
91
86
  export function HandlePlayable({
92
87
  item,
93
88
  isModal,
94
- modalHeight,
95
- modalWidth,
96
89
  mode,
97
90
  groupId,
98
91
  }: Props): React.ReactElement | null {
99
92
  const state = usePickFromState();
100
93
 
101
- const { width: screenWidth, height: screenHeight } =
102
- useDimensions(dimensionsContext);
103
-
104
94
  const { closeVideoModal } = useNavigation();
105
95
 
106
96
  const [Player, playerModuleProperties] = getPlayer(item, state);
@@ -118,9 +108,7 @@ export function HandlePlayable({
118
108
  if (!isModal) {
119
109
  closeVideoModal();
120
110
  }
121
- }, []);
122
111
 
123
- React.useEffect(() => {
124
112
  const castStateHandler = async () => {
125
113
  const castState = await CastPlugin?.getCastState();
126
114
  setCasting(castState === "Connected");
@@ -142,23 +130,29 @@ export function HandlePlayable({
142
130
  }, []);
143
131
 
144
132
  React.useEffect(() => {
145
- if (casting) {
146
- setPlayable({ Component: CastPlugin?.CastHandler });
147
- } else {
148
- setPlayable({ Component: PlayerContainer });
149
- }
133
+ setPlayable({
134
+ Component: casting ? CastPlugin?.CastHandler : PlayerContainer,
135
+ });
150
136
  }, [casting]);
151
137
 
152
- const Component = playable?.Component;
138
+ const { width: screenWidth, height: screenHeight } = useDimensions("window");
139
+
140
+ const modalSize = useModalSize();
153
141
 
154
142
  const style = React.useMemo(
155
143
  () => ({
156
- width: isModal ? modalWidth : mode === "PIP" ? "100%" : screenWidth,
157
- height: isModal ? modalHeight : mode === "PIP" ? "100%" : screenHeight,
144
+ width: isModal ? modalSize.width : mode === "PIP" ? "100%" : screenWidth,
145
+ height: isModal
146
+ ? modalSize.height
147
+ : mode === "PIP"
148
+ ? "100%"
149
+ : screenHeight,
158
150
  }),
159
- [screenWidth, screenHeight, modalHeight, modalWidth, isModal, mode]
151
+ [screenWidth, screenHeight, modalSize, isModal, mode]
160
152
  );
161
153
 
154
+ const Component = playable?.Component;
155
+
162
156
  if (Component) {
163
157
  return (
164
158
  <Component
@@ -174,5 +168,5 @@ export function HandlePlayable({
174
168
  );
175
169
  }
176
170
 
177
- return !isModal ? <BufferAnimation videoStyle={style as ViewStyle} /> : null;
171
+ return !isModal ? <BufferAnimation videoStyle={style} /> : null;
178
172
  }
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks/usePickFromState";
3
+ import { getBackgroundImageUrl } from "../utils";
4
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
5
+
6
+ export const LayoutBackground = ({
7
+ Background,
8
+ children,
9
+ }: {
10
+ Background: React.ComponentType<any>;
11
+ children: React.ReactNode;
12
+ }) => {
13
+ const theme = useTheme();
14
+
15
+ const { remoteConfigurations } = usePickFromState(["remoteConfigurations"]);
16
+
17
+ const backgroundColor = theme.app_background_color;
18
+ const backgroundImageUrl = getBackgroundImageUrl(remoteConfigurations);
19
+
20
+ return (
21
+ <Background
22
+ backgroundColor={backgroundColor}
23
+ backgroundImageUrl={backgroundImageUrl}
24
+ >
25
+ {children}
26
+ </Background>
27
+ );
28
+ };
@@ -1,9 +1,5 @@
1
1
  import * as React from "react";
2
- import { View, StyleSheet } from "react-native";
3
- import { ScreenLayoutContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenLayoutContext";
4
- import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
5
- import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
6
- import { useScreenConfiguration } from "../../River/useScreenConfiguration";
2
+ import { StyleSheet, View } from "react-native";
7
3
 
8
4
  type Props = {
9
5
  children: React.ReactNode;
@@ -12,33 +8,33 @@ type Props = {
12
8
  };
13
9
 
14
10
  const styles = StyleSheet.create({
15
- container: { position: "absolute", top: 0, zIndex: 10, width: 1920 },
11
+ container: {
12
+ position: "absolute",
13
+ top: 0,
14
+ zIndex: 10,
15
+ flex: 1,
16
+ width: "100%",
17
+ },
18
+ themeStyles: {
19
+ // limits the height of the focusable container of the TopMenuBarTV component
20
+ // to prevent it from being overlapped by the screen content,
21
+ // as it makes TopMenuBarTV unfocusable on tvOS
22
+ maxHeight: 1,
23
+ },
16
24
  });
17
25
 
18
26
  export const NavBarContainer = ({ children, isVisible, onReady }: Props) => {
19
- const screenLayout = React.useContext(ScreenLayoutContext);
20
- const screenMarginTop = screenLayout?.screenMarginTop || 0;
21
- const screen = useCurrentScreenData();
22
- const screenConfig = useScreenConfiguration(screen?.id);
23
-
24
- const themeStyles = React.useMemo(
25
- () => ({
26
- // limits the height of the focusable container of the TopMenuBarTV component
27
- // to prevent it from being overlapped by the screen content,
28
- // as it makes TopMenuBarTV unfocusable on tvOS
29
- maxHeight: ifEmptyUseFallback(screenConfig?.marginTop, screenMarginTop),
30
- }),
31
- [screenLayout, screenConfig]
32
- );
33
-
34
27
  React.useEffect(() => {
35
28
  setTimeout(() => {
36
29
  onReady?.(true);
37
30
  }, 0);
38
- }, []);
31
+ }, [onReady]);
39
32
 
40
33
  return isVisible ? (
41
- <View testID="nav-bar-container" style={[styles.container, themeStyles]}>
34
+ <View
35
+ testID="nav-bar-container"
36
+ style={[styles.container, styles.themeStyles]}
37
+ >
42
38
  {children}
43
39
  </View>
44
40
  ) : null;
@@ -22,7 +22,6 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
22
22
  import { NavBarContainer } from "./NavBarContainer";
23
23
 
24
24
  type ComponentsExtraProps = {
25
- Background?: Record<string, any>;
26
25
  NavBar?: Record<string, any>;
27
26
  };
28
27
 
@@ -55,8 +54,11 @@ export const ScreenContainer = React.memo(function ScreenContainer({
55
54
  ComponentsExtraProps,
56
55
  NavBar,
57
56
  }: Props) {
58
- const { screenMarginBottom } = React.useContext(ScreenLayoutContext);
57
+ const { screenMarginBottom, resetScreenLayout } =
58
+ React.useContext(ScreenLayoutContext);
59
+
59
60
  const { currentRoute, screenData } = useNavigation();
61
+
60
62
  const screen = useCurrentScreenData();
61
63
 
62
64
  const { marginBottom, backgroundColor, paddingTop, paddingBottom } =
@@ -65,6 +67,10 @@ export const ScreenContainer = React.memo(function ScreenContainer({
65
67
  const theme = useTheme();
66
68
  const getThemeValue = React.useCallback(R.propOr(0, R.__, theme), [theme]);
67
69
 
70
+ React.useEffect(() => {
71
+ resetScreenLayout();
72
+ }, [currentRoute]);
73
+
68
74
  const fullscreen = React.useCallback(
69
75
  displayFullScreen({ currentRoute, screenData }),
70
76
  [currentRoute, screenData]
@@ -60,10 +60,15 @@ export function ScreenLayoutContextProvider(props: {
60
60
  initialState
61
61
  );
62
62
 
63
+ const resetScreenLayout = React.useCallback(() => {
64
+ setScreenLayout(initialState);
65
+ }, [initialState]);
66
+
63
67
  const screenLayoutValue = React.useMemo(
64
68
  () => ({
65
69
  ...screenLayout,
66
70
  setScreenLayout,
71
+ resetScreenLayout,
67
72
  }),
68
73
  [screenLayout]
69
74
  );