@applicaster/zapp-react-native-ui-components 14.0.0-rc.9 → 15.0.0-alpha.1089439460

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 (183) hide show
  1. package/Components/AnimatedInOut/index.tsx +68 -23
  2. package/Components/AudioPlayer/index.tsx +15 -0
  3. package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
  4. package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
  5. package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
  6. package/Components/AudioPlayer/mobile/index.tsx +18 -0
  7. package/Components/AudioPlayer/{Artwork.tsx → tv/Artwork.tsx} +3 -2
  8. package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
  9. package/Components/AudioPlayer/tv/Layout.tsx +168 -0
  10. package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +7 -1
  11. package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +6 -2
  12. package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +6 -2
  13. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
  14. package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
  15. package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
  16. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -2
  17. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -2
  18. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
  19. package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +11 -5
  20. package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +17 -58
  21. package/Components/AudioPlayer/types.ts +40 -0
  22. package/Components/BaseFocusable/index.tsx +23 -12
  23. package/Components/Cell/Cell.tsx +91 -64
  24. package/Components/Cell/CellWithFocusable.tsx +3 -0
  25. package/Components/Cell/FocusableWrapper.tsx +44 -0
  26. package/Components/Cell/TvOSCellComponent.tsx +92 -17
  27. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  28. package/Components/Cell/index.js +7 -3
  29. package/Components/ComponentResolver/index.ts +1 -1
  30. package/Components/FeedLoader/FeedLoader.tsx +7 -16
  31. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  32. package/Components/FeedLoader/index.js +2 -8
  33. package/Components/Focusable/Focusable.tsx +12 -3
  34. package/Components/Focusable/FocusableTvOS.tsx +5 -5
  35. package/Components/Focusable/FocusableiOS.tsx +2 -2
  36. package/Components/Focusable/Touchable.tsx +5 -3
  37. package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
  38. package/Components/Focusable/index.android.tsx +19 -11
  39. package/Components/Focusable/index.tsx +1 -1
  40. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
  41. package/Components/FocusableList/FocusableItem.tsx +4 -3
  42. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  43. package/Components/FocusableList/hooks/useCellState.android.ts +13 -3
  44. package/Components/FocusableList/index.tsx +20 -9
  45. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  46. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
  47. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -21
  48. package/Components/HandlePlayable/HandlePlayable.tsx +39 -74
  49. package/Components/HandlePlayable/const.ts +3 -0
  50. package/Components/HandlePlayable/utils.ts +74 -0
  51. package/Components/HookRenderer/HookRenderer.tsx +5 -1
  52. package/Components/Layout/TV/LayoutBackground.tsx +1 -1
  53. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  54. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
  55. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
  56. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -39
  57. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
  58. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
  59. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +65 -17
  60. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +21 -3
  61. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +6 -3
  62. package/Components/MasterCell/DefaultComponents/Text/index.tsx +26 -6
  63. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  64. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  65. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  66. package/Components/MasterCell/elementMapper.tsx +1 -2
  67. package/Components/MasterCell/index.tsx +1 -1
  68. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  69. package/Components/MasterCell/utils/index.ts +11 -5
  70. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
  71. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
  72. package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
  73. package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
  74. package/Components/PlayerContainer/PlayerContainer.tsx +45 -47
  75. package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
  76. package/Components/PlayerContainer/index.ts +1 -1
  77. package/Components/PlayerImageBackground/index.tsx +4 -23
  78. package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -43
  79. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapHeightContext.ts +8 -0
  80. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapRefContext.ts +8 -0
  81. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
  82. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
  83. package/Components/River/RefreshControl.tsx +11 -17
  84. package/Components/River/RiverItem.tsx +3 -0
  85. package/Components/River/TV/River.tsx +2 -17
  86. package/Components/River/TV/index.tsx +3 -1
  87. package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
  88. package/Components/River/TV/withRiverDataLoader.tsx +17 -0
  89. package/Components/River/TV/withTVEventHandler.tsx +1 -1
  90. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
  91. package/Components/River/__tests__/river.test.js +12 -26
  92. package/Components/River/index.tsx +1 -1
  93. package/Components/Screen/TV/hooks/useInitialFocus.ts +14 -4
  94. package/Components/Screen/__tests__/Screen.test.tsx +28 -29
  95. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  96. package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
  97. package/Components/Screen/index.tsx +22 -5
  98. package/Components/Screen/navigationHandler.ts +20 -2
  99. package/Components/ScreenResolver/index.tsx +22 -1
  100. package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
  101. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
  102. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
  103. package/Components/ScreenRevealManager/index.ts +1 -0
  104. package/Components/ScreenRevealManager/utils/index.ts +23 -0
  105. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +109 -0
  106. package/Components/Tabs/TV/Tabs.android.tsx +1 -3
  107. package/Components/Tabs/Tabs.tsx +2 -3
  108. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
  109. package/Components/TextInputTv/index.tsx +11 -0
  110. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
  111. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  112. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
  113. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  114. package/Components/VideoLive/animationUtils.ts +3 -3
  115. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +120 -133
  116. package/Components/VideoModal/ModalAnimation/index.ts +2 -13
  117. package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
  118. package/Components/VideoModal/PlayerDetails.tsx +29 -7
  119. package/Components/VideoModal/PlayerWrapper.tsx +25 -215
  120. package/Components/VideoModal/VideoModal.tsx +4 -22
  121. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  122. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +2 -7
  123. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -240
  124. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +9 -1
  125. package/Components/VideoModal/hooks/index.ts +0 -2
  126. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +40 -15
  127. package/Components/VideoModal/hooks/useModalSize.ts +23 -2
  128. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
  129. package/Components/VideoModal/hooks/utils/index.ts +4 -0
  130. package/Components/VideoModal/playerWrapperStyle.ts +70 -0
  131. package/Components/VideoModal/playerWrapperUtils.ts +91 -0
  132. package/Components/VideoModal/utils.ts +13 -0
  133. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
  134. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
  135. package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
  136. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -6
  137. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  138. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
  139. package/Contexts/CellFocusedStateContext/index.tsx +27 -0
  140. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  141. package/Contexts/ScreenContext/index.tsx +46 -6
  142. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  143. package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
  144. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  145. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  146. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  147. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  148. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +6 -10
  149. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  150. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
  151. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
  152. package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
  153. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
  154. package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
  155. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
  156. package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
  157. package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
  158. package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
  159. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
  160. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
  161. package/Decorators/ZappPipesDataConnector/types.ts +29 -0
  162. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  163. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
  164. package/events/index.ts +3 -0
  165. package/package.json +5 -10
  166. package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
  167. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
  168. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
  169. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
  170. package/Components/AudioPlayer/index.ts +0 -1
  171. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
  172. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
  173. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -421
  174. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
  175. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
  176. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
  177. package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
  178. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
  179. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +0 -0
  180. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
  181. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
  182. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
  183. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
@@ -1,17 +1,16 @@
1
1
  import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
2
2
 
3
3
  import { useEffect, useMemo } from "react";
4
- import { useDispatch } from "react-redux";
5
4
 
6
5
  import {
7
6
  useLayoutPresets,
8
- useZappPipesFeeds,
9
- } from "@applicaster/zapp-react-native-redux/hooks";
10
- import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
7
+ useZappPipesFeed,
8
+ } from "@applicaster/zapp-react-native-redux";
11
9
  import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
12
10
  import { Categories } from "./logger";
13
11
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
14
12
  import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute";
13
+
15
14
  import {
16
15
  ZappPipesEntryContext,
17
16
  ZappPipesScreenContext,
@@ -24,9 +23,13 @@ import {
24
23
  } from "@applicaster/zapp-react-native-utils/reactHooks/feed/useInflatedUrl";
25
24
 
26
25
  import { produce } from "immer";
26
+ import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
27
27
  // types reference
28
28
 
29
- declare type CurationEntry = { preset_name: string; feed_url: string };
29
+ declare interface CurationEntry {
30
+ preset_name: string;
31
+ feed_url: string;
32
+ }
30
33
 
31
34
  type Feeds = Record<string, ZappPipesData>;
32
35
 
@@ -122,8 +125,6 @@ export const getFinalComponents = (
122
125
  export const useCurationAPI = (
123
126
  components: Array<ZappUIComponent>
124
127
  ): ZappUIComponent[] => {
125
- const dispatch = useDispatch();
126
-
127
128
  const smartComponents = useMemo(
128
129
  () => components?.filter?.(isSmartComponent) ?? [],
129
130
  [components]
@@ -141,17 +142,15 @@ export const useCurationAPI = (
141
142
  const url = path(SOURCE_PATH, component);
142
143
  const mapping = path(MAPPING_PATH, component);
143
144
 
144
- map[component.id] = mapping
145
- ? getInflatedDataSourceUrl({
146
- source: url,
147
- contexts: {
148
- entry: entryContext,
149
- screen: screenContext,
150
- search: getSearchContext(searchContext, mapping),
151
- },
152
- mapping,
153
- })
154
- : url;
145
+ map[component.id] = getInflatedDataSourceUrl({
146
+ source: url,
147
+ contexts: {
148
+ entry: entryContext,
149
+ screen: screenContext,
150
+ search: getSearchContext(searchContext, mapping),
151
+ },
152
+ mapping,
153
+ });
155
154
  });
156
155
 
157
156
  return map;
@@ -159,19 +158,21 @@ export const useCurationAPI = (
159
158
 
160
159
  const urls = useMemo<string[]>(() => Object.values(urlsMap), [urlsMap]);
161
160
 
161
+ const loadPipesDataDispatcher = useLoadPipesDataDispatch();
162
+
162
163
  useEffect(() => {
163
164
  urls.forEach((url, index) => {
164
165
  if (url) {
165
- dispatch(loadPipesData(url, { clearCache: false }));
166
+ loadPipesDataDispatcher(url, { clearCache: false });
166
167
  } else {
167
168
  logger.log_error("Curation url is empty", {
168
169
  componentId: smartComponents?.[index]?.id,
169
170
  });
170
171
  }
171
172
  });
172
- }, [urls]);
173
+ }, [urls, loadPipesDataDispatcher]);
173
174
 
174
- const feeds = useZappPipesFeeds(urls);
175
+ const feeds = useZappPipesFeed(urls);
175
176
  const layoutPresets = useLayoutPresets();
176
177
 
177
178
  const enrichedComponents = useMemo(() => {
@@ -1,18 +1,17 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
3
- import {
4
- findPluginByType,
5
- findPluginByIdentifier,
6
- } from "@applicaster/zapp-react-native-utils/pluginUtils";
7
2
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
8
3
  import {
9
4
  useDimensions,
5
+ useIsTablet as isTablet,
10
6
  useNavigation,
11
7
  } from "@applicaster/zapp-react-native-utils/reactHooks";
12
8
 
13
9
  import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
14
10
  import { PlayerContainer } from "../PlayerContainer";
15
11
  import { useModalSize } from "../VideoModal/hooks";
12
+ import { ViewStyle } from "react-native";
13
+ import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
14
+ import { findCastPlugin, getPlayer } from "./utils";
16
15
 
17
16
  type Props = {
18
17
  item: ZappEntry;
@@ -23,80 +22,40 @@ type Props = {
23
22
  groupId?: string;
24
23
  };
25
24
 
26
- const YOUTUBE_PLUGIN_ID = "youtube-player-qb";
27
- const CHROMECAST_PLUGIN_ID = "chromecast_qb";
28
-
29
- const getPlayerWithModuleProperties = (
30
- PlayerModule: ZappPlugin
31
- ): [ZappPlugin, PlayerModuleProperties] => {
32
- const getPlayerModuleProperties = R.ifElse(
33
- R.is(Object) && R.has("Component"),
34
- R.omit(["Component"]),
35
- () => ({})
36
- );
37
-
38
- return [
39
- PlayerModule?.Component || PlayerModule,
40
- getPlayerModuleProperties(PlayerModule),
41
- ];
42
- };
43
-
44
- const getPlayer = (
45
- item: ZappEntry,
46
- state
47
- ): [ZappPlugin, PlayerModuleProperties] => {
48
- const {
49
- plugins,
50
- contentTypes,
51
- rivers,
52
- appData: { layoutVersion },
53
- } = state;
54
-
55
- let PlayerModule;
56
-
57
- if (layoutVersion === "v2") {
58
- const { screen_id } = contentTypes?.[item?.type?.value] || {};
59
- const { type } = rivers?.[screen_id] || {};
60
-
61
- if (type) {
62
- PlayerModule = findPluginByIdentifier(type, plugins)?.module;
63
-
64
- return getPlayerWithModuleProperties(PlayerModule);
65
- }
66
- }
67
-
68
- if (item?.content?.type === "youtube-id") {
69
- PlayerModule = findPluginByIdentifier(YOUTUBE_PLUGIN_ID, plugins)?.module;
70
-
71
- return getPlayerWithModuleProperties(PlayerModule);
72
- }
73
-
74
- PlayerModule = findPluginByType(
75
- "playable",
76
- plugins.filter(({ identifier }) => identifier !== YOUTUBE_PLUGIN_ID)
77
- );
78
-
79
- return getPlayerWithModuleProperties(PlayerModule);
80
- };
81
-
82
25
  type PlayableComponent = {
83
26
  Component: React.ComponentType<any>;
84
27
  };
85
28
 
29
+ const dimensionsContext: "window" | "screen" = platformSelect({
30
+ android_tv: "window",
31
+ amazon: "window",
32
+ // eslint-disable-next-line react-hooks/rules-of-hooks
33
+ default: isTablet() ? "window" : "screen", // on tablet, window represents correct values, on phone it's not as the screen could be rotated
34
+ });
35
+
86
36
  export function HandlePlayable({
87
37
  item,
88
38
  isModal,
89
39
  mode,
90
40
  groupId,
91
41
  }: Props): React.ReactElement | null {
92
- const state = usePickFromState();
42
+ const { plugins, contentTypes, rivers, appData } = usePickFromState([
43
+ "plugins",
44
+ "contentTypes",
45
+ "rivers",
46
+ "appData",
47
+ ]);
93
48
 
94
49
  const { closeVideoModal } = useNavigation();
95
50
 
96
- const [Player, playerModuleProperties] = getPlayer(item, state);
51
+ const [Player, playerModuleProperties] = getPlayer(item, {
52
+ plugins,
53
+ contentTypes,
54
+ rivers,
55
+ appData,
56
+ });
97
57
 
98
- const { module: CastPlugin } =
99
- findPluginByIdentifier(CHROMECAST_PLUGIN_ID, state.plugins, true) || {};
58
+ const { module: CastPlugin } = findCastPlugin(plugins);
100
59
 
101
60
  const [playable, setPlayable] =
102
61
  React.useState<Nullable<PlayableComponent>>(null);
@@ -135,19 +94,25 @@ export function HandlePlayable({
135
94
  });
136
95
  }, [casting]);
137
96
 
138
- const { width: screenWidth, height: screenHeight } = useDimensions("window");
97
+ const { width: screenWidth, height: screenHeight } =
98
+ useDimensions(dimensionsContext);
139
99
 
140
100
  const modalSize = useModalSize();
141
101
 
142
102
  const style = React.useMemo(
143
- () => ({
144
- width: isModal ? modalSize.width : mode === "PIP" ? "100%" : screenWidth,
145
- height: isModal
146
- ? modalSize.height
147
- : mode === "PIP"
148
- ? "100%"
149
- : screenHeight,
150
- }),
103
+ () =>
104
+ ({
105
+ width: isModal
106
+ ? modalSize.width
107
+ : mode === "PIP"
108
+ ? "100%"
109
+ : screenWidth,
110
+ height: isModal
111
+ ? modalSize.height
112
+ : mode === "PIP"
113
+ ? "100%"
114
+ : screenHeight,
115
+ }) as ViewStyle,
151
116
  [screenWidth, screenHeight, modalSize, isModal, mode]
152
117
  );
153
118
 
@@ -0,0 +1,3 @@
1
+ export const YOUTUBE_PLUGIN_ID = "youtube-player-qb";
2
+
3
+ export const CHROMECAST_PLUGIN_ID = "chromecast_qb";
@@ -0,0 +1,74 @@
1
+ import {
2
+ findPluginByIdentifier,
3
+ findPluginByType,
4
+ } from "@applicaster/zapp-react-native-utils/pluginUtils";
5
+
6
+ import { CHROMECAST_PLUGIN_ID, YOUTUBE_PLUGIN_ID } from "./const";
7
+ import { omit } from "@applicaster/zapp-react-native-utils/utils";
8
+
9
+ const getPlayerModuleProperties = (PlayerModule: ZappPlugin) => {
10
+ if (PlayerModule?.Component && typeof PlayerModule.Component === "object") {
11
+ return omit(["Component"], PlayerModule);
12
+ }
13
+
14
+ return {};
15
+ };
16
+
17
+ export const getPlayerWithModuleProperties = (
18
+ PlayerModule: ZappPlugin
19
+ ): [ZappPlugin, PlayerModuleProperties] => {
20
+ return [
21
+ PlayerModule?.Component || PlayerModule,
22
+ getPlayerModuleProperties(PlayerModule),
23
+ ];
24
+ };
25
+
26
+ export const findCastPlugin = (plugins: ZappPlugin[]) =>
27
+ findPluginByIdentifier(CHROMECAST_PLUGIN_ID, plugins, true) || {};
28
+
29
+ export const findYoutubePlugin = (plugins: ZappPlugin[]) =>
30
+ findPluginByIdentifier(YOUTUBE_PLUGIN_ID, plugins, true) || {};
31
+
32
+ export const getPlayer = (
33
+ item: ZappEntry,
34
+ {
35
+ plugins,
36
+ contentTypes,
37
+ rivers,
38
+ appData: { layoutVersion },
39
+ }: {
40
+ plugins: ZappPlugin[];
41
+ contentTypes: Record<string, any>;
42
+ rivers: Record<string, any>;
43
+ appData: { layoutVersion: string };
44
+ }
45
+ ): [ZappPlugin, PlayerModuleProperties] => {
46
+ let PlayerModule;
47
+
48
+ if (layoutVersion === "v2") {
49
+ const screen_id = contentTypes?.[item?.type?.value]?.screen_id;
50
+ const type = rivers?.[screen_id]?.type;
51
+
52
+ if (type) {
53
+ PlayerModule = findPluginByIdentifier(type, plugins)?.module;
54
+
55
+ return getPlayerWithModuleProperties(PlayerModule);
56
+ }
57
+ }
58
+
59
+ if (item?.content?.type === "youtube-id") {
60
+ PlayerModule = findYoutubePlugin(plugins)?.module;
61
+
62
+ return getPlayerWithModuleProperties(PlayerModule);
63
+ }
64
+
65
+ PlayerModule = findPluginByType(
66
+ "playable",
67
+ (plugins as any[]).filter(
68
+ ({ identifier }: { identifier: string }) =>
69
+ identifier !== YOUTUBE_PLUGIN_ID
70
+ )
71
+ );
72
+
73
+ return getPlayerWithModuleProperties(PlayerModule);
74
+ };
@@ -6,17 +6,20 @@ import {
6
6
  } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
7
7
  import { useHookAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks";
8
8
  import { useSetNavbarState } from "@applicaster/zapp-react-native-utils/reactHooks";
9
+ import { PresentationType } from "../ScreenResolver";
9
10
 
10
11
  type Props = {
11
12
  focused?: boolean;
12
13
  parentFocus?: ParentFocus;
13
14
  screenData: HookPluginProps;
15
+ callback: hookCallback;
14
16
  };
15
17
 
16
18
  export const HookRenderer = (props: Props) => {
17
19
  const {
18
20
  focused,
19
- screenData: { callback, payload, hookPlugin },
21
+ screenData: { payload, hookPlugin },
22
+ callback,
20
23
  } = props;
21
24
 
22
25
  const { setVisible: showNavBar } = useSetNavbarState();
@@ -60,6 +63,7 @@ export const HookRenderer = (props: Props) => {
60
63
  hookPlugin,
61
64
  focused,
62
65
  parentFocus,
66
+ presentationType: PresentationType.Hook,
63
67
  }}
64
68
  />
65
69
  );
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks/usePickFromState";
2
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
3
  import { getBackgroundImageUrl } from "../utils";
4
4
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
5
5
 
@@ -7,7 +7,6 @@ import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/
7
7
  import configureStore from "redux-mock-store";
8
8
  import Layout from "../index.web";
9
9
 
10
- // mock useTheme to provide app_background_color
11
10
  jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
12
11
  useTheme: () => ({
13
12
  app_background_color: "#000000",
@@ -23,6 +23,7 @@ type Props = {
23
23
  style: ViewStyle;
24
24
  testID?: string;
25
25
  accessibilityLabel?: string;
26
+ accessibilityHint?: string;
26
27
  cellUUID?: string;
27
28
  extraProps?: Record<string, any>;
28
29
  };
@@ -48,7 +49,9 @@ function getAssetValue(asset, flavour, fallbackAsset = null) {
48
49
  return asset.src || fallbackAsset;
49
50
  }
50
51
 
51
- export function ActionButton(props: Props) {
52
+ export const ActionButton = React.memo(function ActionButtonComponent(
53
+ props: Props
54
+ ) {
52
55
  const { item, action, asset, flavour = "flavour_1", cellUUID } = props;
53
56
  const actionContext = useActions(action?.identifier);
54
57
 
@@ -98,6 +101,7 @@ export function ActionButton(props: Props) {
98
101
  onPress={onPress}
99
102
  testID={props?.testID || `${item?.id}`}
100
103
  accessibilityLabel={props?.accessibilityLabel || `${item?.id}`}
104
+ accessibilityHint={props?.accessibilityHint}
101
105
  accessible={!!(props?.testID || props?.accessibilityLabel)}
102
106
  style={props?.style}
103
107
  >
@@ -118,4 +122,4 @@ export function ActionButton(props: Props) {
118
122
  )}
119
123
  </TouchableOpacity>
120
124
  );
121
- }
125
+ });
@@ -4,7 +4,7 @@ import * as R from "ramda";
4
4
  import { TouchableOpacity } from "react-native";
5
5
  // import { SvgUri } from "react-native-svg";
6
6
 
7
- import { connectToStore } from "@applicaster/zapp-react-native-redux";
7
+ import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
8
8
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
9
9
 
10
10
  import Image from "./Image";
@@ -2,10 +2,8 @@ import React, { useMemo } from "react";
2
2
  import { ImageStyle } from "react-native";
3
3
  import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
4
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
5
- import * as R from "ramda";
6
5
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
7
6
  import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
8
- import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
9
7
 
10
8
  const { Logger } = getXray();
11
9
 
@@ -45,11 +43,6 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
45
43
 
46
44
  const actionContext = useActions(pluginIdentifier);
47
45
 
48
- const accessibilityManager = useAccessibilityManager({});
49
-
50
- const { ttsLabel = "" } =
51
- actionContext?.initialEntryState(item)?.getAccessibility?.(item) || {};
52
-
53
46
  const onPress = (event) => {
54
47
  event?.preventDefault?.();
55
48
 
@@ -67,39 +60,11 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
67
60
  const handleFocus = (focusable) => {
68
61
  const focusedButtonId = getFocusedButtonId(focusable);
69
62
 
70
- wrapperRef?.current?.measure((x, y, width, height, pageX, pageY) => {
71
- const top = pageY;
72
- const bottom = top + height;
73
- const left = pageX;
74
- const right = left + width;
75
-
76
- const boundingRect = {
77
- x,
78
- y,
79
- pageX,
80
- pageY,
81
- width,
82
- height,
83
- top,
84
- bottom,
85
- left,
86
- right,
87
- };
88
-
89
- otherProps?.onToggleFocus?.({
90
- focusable: {
91
- getRect: R.always(boundingRect),
92
- },
93
- focusedButtonId,
94
- mouse: focusable.mouse,
95
- });
63
+ otherProps?.onToggleFocus?.({
64
+ focusable: wrapperRef.current,
65
+ focusedButtonId,
66
+ mouse: focusable.mouse,
96
67
  });
97
-
98
- if (ttsLabel) {
99
- accessibilityManager.readText({
100
- text: ttsLabel,
101
- });
102
- }
103
68
  };
104
69
 
105
70
  const handleBlur = (_focusable, _direction) => {
@@ -20,7 +20,7 @@ const withAppliedDimensions = (style: Style) => (source: Source) => ({
20
20
  });
21
21
 
22
22
  export const withDimensionsHOC = (Component) => {
23
- return function WithDimensions(props: { style: any }) {
23
+ return function WithDimensions(props: Record<string, unknown>) {
24
24
  const theme = useTheme<BaseThemePropertiesMobile>();
25
25
 
26
26
  const useDownScalingImages = toBooleanWithDefaultFalse(
@@ -13,7 +13,7 @@ export const ImageContainer = (props: Props) => {
13
13
  const isActive = useIsScreenActive();
14
14
 
15
15
  const Component =
16
- isVideoPreviewEnabled(props) && isActive ? LiveImage : PureImage;
16
+ isVideoPreviewEnabled(props as Props) && isActive ? LiveImage : PureImage;
17
17
 
18
18
  return <Component {...props} />;
19
19
  };
@@ -28,17 +28,10 @@ interface Props {
28
28
  onAsyncRender: () => void;
29
29
  }
30
30
 
31
- const SecondaryImageComponent = (props: Props) => {
32
- const {
33
- uri,
34
- style,
35
- displayMode,
36
- imageSizing,
37
- fitPosition,
38
- fixedHeight,
39
- fixedWidth,
40
- onAsyncRender,
41
- } = props;
31
+ /** Secondary Image Dynamic does not render until the image is loaded */
32
+ const SecondaryImageDynamic = (props: Props) => {
33
+ const { uri, style, displayMode, imageSizing, fitPosition, onAsyncRender } =
34
+ props;
42
35
 
43
36
  const imageDimension = useGetImageDimensions(
44
37
  uri,
@@ -46,13 +39,9 @@ const SecondaryImageComponent = (props: Props) => {
46
39
  isImageSizingFit(imageSizing) ? undefined : (style.height as number)
47
40
  );
48
41
 
49
- const containerHeight = isDisplayModeFixed(displayMode)
50
- ? fixedHeight
51
- : imageDimension?.height;
42
+ const containerHeight = imageDimension?.height;
52
43
 
53
- const containerWidth = isDisplayModeFixed(displayMode)
54
- ? fixedWidth
55
- : style?.width;
44
+ const containerWidth = style?.width;
56
45
 
57
46
  if (isNil(imageDimension?.aspectRatio)) {
58
47
  return null;
@@ -80,4 +69,63 @@ const SecondaryImageComponent = (props: Props) => {
80
69
  );
81
70
  };
82
71
 
72
+ /** Secondary Image Fixed does not render the image until the image is loaded, but keep container rendered */
73
+ const SecondaryImageFixed = (props: Props) => {
74
+ const {
75
+ uri,
76
+ style,
77
+ displayMode,
78
+ imageSizing,
79
+ fitPosition,
80
+ fixedHeight,
81
+ fixedWidth,
82
+ onAsyncRender,
83
+ } = props;
84
+
85
+ const imageDimension = useGetImageDimensions(
86
+ uri,
87
+ style.width as number,
88
+ isImageSizingFit(imageSizing) ? undefined : (style.height as number)
89
+ );
90
+
91
+ return (
92
+ <View style={style} onLayout={onAsyncRender}>
93
+ {isNil(imageDimension?.aspectRatio) ? null : (
94
+ <Image
95
+ {...props}
96
+ source={{ uri }}
97
+ style={{
98
+ ...getStyle({
99
+ imageSizing,
100
+ fitPosition,
101
+ displayMode,
102
+ imageDimension,
103
+ containerHeight: fixedHeight,
104
+ containerWidth: fixedWidth,
105
+ }),
106
+ borderRadius: style.borderRadius,
107
+ aspectRatio: imageDimension.aspectRatio,
108
+ }}
109
+ />
110
+ )}
111
+ </View>
112
+ );
113
+ };
114
+
115
+ const SecondaryImageComponent = (props: Props) => {
116
+ const { uri, displayMode } = props;
117
+
118
+ if (!uri) {
119
+ return null;
120
+ }
121
+
122
+ const isFixed = isDisplayModeFixed(displayMode);
123
+
124
+ return isFixed ? (
125
+ <SecondaryImageFixed {...props} />
126
+ ) : (
127
+ <SecondaryImageDynamic {...props} />
128
+ );
129
+ };
130
+
83
131
  export const SecondaryImage = withAsyncRenderHOC(SecondaryImageComponent);
@@ -4,9 +4,26 @@ import { render } from "@testing-library/react-native";
4
4
  import { SecondaryImage } from "../Image";
5
5
 
6
6
  describe("SecondaryImage - Image", () => {
7
- it("SecondaryImage should not render if no aspect ratio", async () => {
7
+ it("SecondaryImage should not render if no uri", async () => {
8
8
  const wrapper = await render(
9
- <SecondaryImage uri="" style={{ width: 100 }} />
9
+ <SecondaryImage
10
+ displayMode="dynamic"
11
+ uri={undefined}
12
+ style={{ width: 100 }}
13
+ />
14
+ );
15
+
16
+ expect(wrapper.toJSON()).toEqual(null);
17
+ expect(wrapper.toJSON()).toMatchSnapshot();
18
+ });
19
+
20
+ it("SecondaryImage should not render if no aspect ratio (dynamic)", async () => {
21
+ const wrapper = await render(
22
+ <SecondaryImage
23
+ displayMode="dynamic"
24
+ uri="someurl"
25
+ style={{ width: 100 }}
26
+ />
10
27
  );
11
28
 
12
29
  expect(wrapper.toJSON()).toEqual(null);
@@ -16,7 +33,8 @@ describe("SecondaryImage - Image", () => {
16
33
  it("SecondaryImage should render if known dimensions", async () => {
17
34
  const wrapper = await render(
18
35
  <SecondaryImage
19
- uri=""
36
+ uri="someUrl"
37
+ displayMode="dynamic"
20
38
  style={{ width: 100, height: 100, borderRadius: 10 }}
21
39
  />
22
40
  );
@@ -1,6 +1,8 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`SecondaryImage - Image SecondaryImage should not render if no aspect ratio 1`] = `null`;
3
+ exports[`SecondaryImage - Image SecondaryImage should not render if no aspect ratio (dynamic) 1`] = `null`;
4
+
5
+ exports[`SecondaryImage - Image SecondaryImage should not render if no uri 1`] = `null`;
4
6
 
5
7
  exports[`SecondaryImage - Image SecondaryImage should render if known dimensions 1`] = `
6
8
  <View
@@ -14,10 +16,11 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
14
16
  }
15
17
  >
16
18
  <Image
19
+ displayMode="dynamic"
17
20
  onAsyncRender={[Function]}
18
21
  source={
19
22
  {
20
- "uri": "",
23
+ "uri": "someUrl",
21
24
  }
22
25
  }
23
26
  style={
@@ -28,7 +31,7 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
28
31
  "width": 100,
29
32
  }
30
33
  }
31
- uri=""
34
+ uri="someUrl"
32
35
  />
33
36
  </View>
34
37
  `;