@applicaster/zapp-react-native-ui-components 15.0.0-rc.99 → 15.1.0-rc.2

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 (114) hide show
  1. package/Components/BaseFocusable/index.ios.ts +2 -12
  2. package/Components/Cell/FocusableWrapper.tsx +0 -3
  3. package/Components/Cell/TvOSCellComponent.tsx +0 -5
  4. package/Components/Focusable/Focusable.tsx +2 -4
  5. package/Components/Focusable/FocusableTvOS.tsx +1 -18
  6. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +0 -1
  7. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -30
  8. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +39 -28
  9. package/Components/GeneralContentScreen/__tests__/GeneralContentScreen.test.tsx +104 -0
  10. package/Components/GeneralContentScreen/utils/__tests__/getScreenDataSource.test.ts +19 -0
  11. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  12. package/Components/GeneralContentScreen/utils/getScreenDataSource.ts +9 -0
  13. package/Components/HandlePlayable/HandlePlayable.tsx +24 -42
  14. package/Components/HandlePlayable/utils.ts +31 -0
  15. package/Components/HookRenderer/HookRenderer.tsx +40 -10
  16. package/Components/HookRenderer/__tests__/HookRenderer.test.tsx +60 -0
  17. package/Components/Layout/TV/LayoutBackground.tsx +2 -5
  18. package/Components/Layout/TV/ScreenContainer.tsx +6 -2
  19. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +5 -0
  20. package/Components/Layout/TV/index.tsx +4 -3
  21. package/Components/Layout/TV/index.web.tsx +4 -3
  22. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  23. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +10 -4
  24. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +1 -5
  25. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +3 -11
  26. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +1 -9
  27. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +14 -15
  28. package/Components/MasterCell/DefaultComponents/LiveImage/__tests__/prepareEntry.test.ts +352 -0
  29. package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +136 -0
  30. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +34 -16
  31. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +6 -7
  32. package/Components/MasterCell/DefaultComponents/Text/index.tsx +2 -6
  33. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +2 -6
  34. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +11 -233
  35. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +15 -19
  36. package/Components/Navigator/StackNavigator.tsx +6 -0
  37. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
  38. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +18 -17
  39. package/Components/OfflineHandler/__tests__/index.test.tsx +18 -27
  40. package/Components/PlayerContainer/PlayerContainer.tsx +14 -32
  41. package/Components/PreloaderWrapper/__tests__/index.test.tsx +26 -0
  42. package/Components/PreloaderWrapper/index.tsx +15 -0
  43. package/Components/River/ComponentsMap/ComponentsMap.tsx +3 -4
  44. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  45. package/Components/River/RefreshControl.tsx +9 -3
  46. package/Components/River/RiverItem.tsx +26 -20
  47. package/Components/River/TV/River.tsx +14 -31
  48. package/Components/River/TV/index.tsx +4 -8
  49. package/Components/River/TV/withTVEventHandler.tsx +36 -0
  50. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +0 -1
  51. package/Components/River/__tests__/componentsMap.test.js +0 -38
  52. package/Components/Screen/TV/index.web.tsx +2 -4
  53. package/Components/Screen/__tests__/Screen.test.tsx +43 -65
  54. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +44 -68
  55. package/Components/Screen/hooks.ts +76 -5
  56. package/Components/Screen/index.tsx +10 -3
  57. package/Components/Screen/orientationHandler.ts +3 -3
  58. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +46 -0
  59. package/Components/ScreenFeedLoader/__tests__/ScreenFeedLoader.test.tsx +94 -0
  60. package/Components/ScreenFeedLoader/index.ts +1 -0
  61. package/Components/ScreenResolver/__tests__/screenResolver.test.js +24 -0
  62. package/Components/ScreenResolver/hooks/index.ts +3 -0
  63. package/Components/ScreenResolver/hooks/useGetComponent.ts +15 -0
  64. package/Components/ScreenResolver/hooks/useScreenComponentResolver.tsx +90 -0
  65. package/Components/ScreenResolver/index.tsx +9 -115
  66. package/Components/ScreenResolver/utils/__tests__/getScreenTypeProps.test.ts +45 -0
  67. package/Components/ScreenResolver/utils/getScreenTypeProps.ts +43 -0
  68. package/Components/ScreenResolver/utils/index.ts +1 -0
  69. package/Components/ScreenResolver/withDefaultScreenContext.tsx +16 -0
  70. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +25 -0
  71. package/Components/ScreenResolverFeedProvider/__tests__/ScreenResolverFeedProvider.test.tsx +44 -0
  72. package/Components/ScreenResolverFeedProvider/index.ts +1 -0
  73. package/Components/ScreenRevealManager/ScreenRevealManager.ts +8 -40
  74. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +69 -86
  75. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +4 -1
  76. package/Components/Tabs/TabContent.tsx +4 -7
  77. package/Components/Transitioner/Scene.tsx +9 -15
  78. package/Components/Transitioner/index.js +3 -3
  79. package/Components/VideoLive/LiveImageManager.ts +199 -54
  80. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -33
  81. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +2 -17
  82. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  83. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +7 -15
  84. package/Components/VideoModal/utils.ts +9 -12
  85. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  86. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +6 -4
  87. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  88. package/Components/ZappUIComponent/index.tsx +12 -6
  89. package/Components/index.js +1 -1
  90. package/Contexts/ScreenContext/__tests__/index.test.tsx +57 -0
  91. package/Contexts/ScreenContext/index.tsx +64 -26
  92. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  93. package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
  94. package/Decorators/Analytics/index.tsx +5 -6
  95. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +0 -1
  96. package/Decorators/ConfigurationWrapper/const.ts +0 -1
  97. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
  98. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
  99. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  100. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  101. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  102. package/Helpers/DataSourceHelper/index.js +19 -0
  103. package/package.json +5 -5
  104. package/Components/MasterCell/DefaultComponents/Text/utils/__tests__/withAdjustedLineHeight.test.ts +0 -46
  105. package/Components/MasterCell/DefaultComponents/Text/utils/index.ts +0 -21
  106. package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +0 -57
  107. package/Components/PlayerContainer/ErrorDisplay/index.ts +0 -9
  108. package/Components/PlayerContainer/useRestrictMobilePlayback.tsx +0 -101
  109. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +0 -30
  110. package/Components/River/TV/utils/index.ts +0 -4
  111. package/Components/River/TV/withFocusableGroupForContent.tsx +0 -71
  112. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +0 -80
  113. package/Helpers/DataSourceHelper/index.ts +0 -19
  114. /package/Components/HookRenderer/{index.tsx → index.ts} +0 -0
@@ -1,15 +1,9 @@
1
- import { getPluginIdentifier, memoizedGetPluginIdentifier } from "..";
1
+ import { getPluginIdentifier } from "..";
2
2
 
3
3
  describe("getPluginIdentifier", () => {
4
4
  const prefix = "tv_buttons";
5
5
 
6
- beforeAll(() => {
7
- memoizedGetPluginIdentifier.clear();
8
- });
9
-
10
- it("returns the first valid plugin identifier", () => {
11
- expect.assertions(2);
12
-
6
+ it("get first plugin identifier", () => {
13
7
  const configuration = {
14
8
  tv_buttons_button_1_other: "value",
15
9
  tv_buttons_button_1_assign_action:
@@ -19,21 +13,13 @@ describe("getPluginIdentifier", () => {
19
13
  };
20
14
 
21
15
  const index = 0;
22
- const result = getPluginIdentifier(configuration, prefix, index);
23
16
 
24
- const memoizedResult = memoizedGetPluginIdentifier(
25
- configuration,
26
- prefix,
27
- index
28
- );
17
+ const result = getPluginIdentifier(configuration, prefix, index);
29
18
 
30
19
  expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
31
- expect(memoizedResult).toEqual(result);
32
20
  });
33
21
 
34
- it("returns the second valid plugin identifier", () => {
35
- expect.assertions(2);
36
-
22
+ it("get second plugin identifier", () => {
37
23
  const configuration = {
38
24
  tv_buttons_button_1_other: "value_1",
39
25
  tv_buttons_button_1_assign_action:
@@ -44,216 +30,24 @@ describe("getPluginIdentifier", () => {
44
30
  };
45
31
 
46
32
  const index = 1;
47
- const result = getPluginIdentifier(configuration, prefix, index);
48
33
 
49
- const memoizedResult = memoizedGetPluginIdentifier(
50
- configuration,
51
- prefix,
52
- index
53
- );
34
+ const result = getPluginIdentifier(configuration, prefix, index);
54
35
 
55
36
  expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
56
- expect(memoizedResult).toEqual(result);
57
37
  });
58
38
 
59
- it("returns undefined when there are no assign_action keys", () => {
60
- expect.assertions(2);
61
-
39
+ it("get undefined if no assign_actions at all", () => {
62
40
  const configuration = {};
63
- const index = 0;
64
-
65
- const result = getPluginIdentifier(configuration, prefix, index);
66
-
67
- const memoizedResult = memoizedGetPluginIdentifier(
68
- configuration,
69
- prefix,
70
- index
71
- );
72
-
73
- expect(result).toBeUndefined();
74
- expect(memoizedResult).toBeUndefined();
75
- });
76
-
77
- it("skips undefined values and returns the correct plugin identifier", () => {
78
- expect.assertions(2);
79
-
80
- const configuration = {
81
- tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
82
- tv_buttons_button_2_assign_action: undefined,
83
- tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
84
- };
85
-
86
- const index = 1;
87
- const result = getPluginIdentifier(configuration, prefix, index);
88
-
89
- const memoizedResult = memoizedGetPluginIdentifier(
90
- configuration,
91
- prefix,
92
- index
93
- );
94
-
95
- expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
96
- expect(memoizedResult).toEqual(result);
97
- });
98
-
99
- it("handles missing intermediate keys and returns the correct plugin identifier", () => {
100
- expect.assertions(2);
101
-
102
- const configuration = {
103
- tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
104
- tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
105
- };
106
-
107
- const index = 1;
108
- const result = getPluginIdentifier(configuration, prefix, index);
109
-
110
- const memoizedResult = memoizedGetPluginIdentifier(
111
- configuration,
112
- prefix,
113
- index
114
- );
115
-
116
- expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
117
- expect(memoizedResult).toEqual(result);
118
- });
119
-
120
- it("skips empty string values and returns the first non-empty assign_action", () => {
121
- expect.assertions(2);
122
-
123
- const configuration = {
124
- tv_buttons_button_1_assign_action: "",
125
- tv_buttons_button_2_assign_action: "tv_buttons_button_2_assign_action",
126
- };
127
41
 
128
42
  const index = 0;
129
- const result = getPluginIdentifier(configuration, prefix, index);
130
-
131
- const memoizedResult = memoizedGetPluginIdentifier(
132
- configuration,
133
- prefix,
134
- index
135
- );
136
-
137
- expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
138
- expect(memoizedResult).toEqual(result);
139
- });
140
-
141
- it("returns undefined for negative index", () => {
142
- expect.assertions(2);
143
-
144
- const configuration = {
145
- tv_buttons_button_1_assign_action: "a",
146
- tv_buttons_button_2_assign_action: "b",
147
- };
148
43
 
149
- const index = -1;
150
44
  const result = getPluginIdentifier(configuration, prefix, index);
151
45
 
152
- const memoizedResult = memoizedGetPluginIdentifier(
153
- configuration,
154
- prefix,
155
- index
156
- );
157
-
158
46
  expect(result).toBeUndefined();
159
- expect(memoizedResult).toBeUndefined();
160
- });
161
-
162
- it("returns undefined for out-of-bounds index", () => {
163
- expect.assertions(2);
164
-
165
- const configuration = {
166
- tv_buttons_button_1_assign_action: "a",
167
- tv_buttons_button_2_assign_action: "b",
168
- };
169
-
170
- const index = 5;
171
- const result = getPluginIdentifier(configuration, prefix, index);
172
-
173
- const memoizedResult = memoizedGetPluginIdentifier(
174
- configuration,
175
- prefix,
176
- index
177
- );
178
-
179
- expect(result).toBeUndefined();
180
- expect(memoizedResult).toBeUndefined();
181
- });
182
-
183
- it("ignores keys with wrong prefix or format", () => {
184
- expect.assertions(2);
185
-
186
- const configuration = {
187
- tv_buttons_button_1_assign_action: "a",
188
- tv_buttons_wrongprefix_2_assign_action: "b",
189
- tv_buttons_button_x_assign_action: "c",
190
- };
191
-
192
- const index = 1;
193
- const result = getPluginIdentifier(configuration, prefix, index);
194
-
195
- const memoizedResult = memoizedGetPluginIdentifier(
196
- configuration,
197
- prefix,
198
- index
199
- );
200
-
201
- expect(result).toBeUndefined();
202
- expect(memoizedResult).toBeUndefined();
203
- });
204
-
205
- it("returns undefined if all assign_actions are null or empty", () => {
206
- expect.assertions(2);
207
-
208
- const configuration = {
209
- tv_buttons_button_1_assign_action: null,
210
- tv_buttons_button_2_assign_action: undefined,
211
- tv_buttons_button_3_assign_action: "",
212
- };
213
-
214
- const index = 0;
215
- const result = getPluginIdentifier(configuration, prefix, index);
216
-
217
- const memoizedResult = memoizedGetPluginIdentifier(
218
- configuration,
219
- prefix,
220
- index
221
- );
222
-
223
- expect(result).toBeUndefined();
224
- expect(memoizedResult).toBeUndefined();
225
- });
226
-
227
- it("handles non-string values correctly", () => {
228
- expect.assertions(6);
229
-
230
- const configuration = {
231
- tv_buttons_button_1_assign_action: 123,
232
- tv_buttons_button_2_assign_action: true,
233
- tv_buttons_button_3_assign_action: { nested: "value" },
234
- };
235
-
236
- expect(getPluginIdentifier(configuration, prefix, 0)).toEqual(123);
237
- expect(getPluginIdentifier(configuration, prefix, 1)).toEqual(true);
238
-
239
- expect(getPluginIdentifier(configuration, prefix, 2)).toEqual({
240
- nested: "value",
241
- });
242
-
243
- expect(memoizedGetPluginIdentifier(configuration, prefix, 0)).toEqual(123);
244
- expect(memoizedGetPluginIdentifier(configuration, prefix, 1)).toEqual(true);
245
-
246
- expect(memoizedGetPluginIdentifier(configuration, prefix, 2)).toEqual({
247
- nested: "value",
248
- });
249
47
  });
250
48
  });
251
49
 
252
- describe("getPluginIdentifier - when configuration has duplicate values", () => {
253
- beforeAll(() => {
254
- memoizedGetPluginIdentifier.clear();
255
- });
256
-
50
+ describe("getPluginIdentifier - when configuration has same values for different keys", () => {
257
51
  const prefix = "tv_buttons";
258
52
 
259
53
  const configuration = {
@@ -261,35 +55,19 @@ describe("getPluginIdentifier - when configuration has duplicate values", () =>
261
55
  tv_buttons_button_2_assign_action: "navigation_action",
262
56
  };
263
57
 
264
- it("returns the first plugin identifier when values are identical", () => {
265
- expect.assertions(2);
266
-
58
+ it("get first plugin identifier", () => {
267
59
  const index = 0;
268
- const result = getPluginIdentifier(configuration, prefix, index);
269
60
 
270
- const memoizedResult = memoizedGetPluginIdentifier(
271
- configuration,
272
- prefix,
273
- index
274
- );
61
+ const result = getPluginIdentifier(configuration, prefix, index);
275
62
 
276
63
  expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
277
- expect(memoizedResult).toEqual(result);
278
64
  });
279
65
 
280
- it("returns the second plugin identifier when values are identical", () => {
281
- expect.assertions(2);
282
-
66
+ it("get second plugin identifier", () => {
283
67
  const index = 1;
284
- const result = getPluginIdentifier(configuration, prefix, index);
285
68
 
286
- const memoizedResult = memoizedGetPluginIdentifier(
287
- configuration,
288
- prefix,
289
- index
290
- );
69
+ const result = getPluginIdentifier(configuration, prefix, index);
291
70
 
292
71
  expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
293
- expect(memoizedResult).toEqual(result);
294
72
  });
295
73
  });
@@ -1,7 +1,7 @@
1
1
  import * as R from "ramda";
2
- import memoizee from "memoizee";
3
2
 
4
3
  import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
4
+ import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
5
5
 
6
6
  export const getButtonsCount = (
7
7
  configuration: Record<string, unknown>,
@@ -21,26 +21,22 @@ export const getPluginIdentifier = (
21
21
  configuration: Record<string, unknown>,
22
22
  prefix: string,
23
23
  index: number
24
- ): string | undefined => {
25
- const re = new RegExp(`${prefix}_button_\\d_assign_action`);
26
- let count = 0;
27
-
28
- for (const [key, value] of Object.entries(configuration)) {
29
- if (
30
- key.startsWith(`${prefix}_button`) &&
31
- re.test(key) &&
32
- value != null &&
33
- value !== ""
34
- ) {
35
- if (count === index) return value as string;
36
- count++;
37
- }
38
- }
24
+ ): string => {
25
+ const match = `${prefix}_button_\\d_assign_action`;
26
+ const re = new RegExp(match);
39
27
 
40
- return undefined;
41
- };
28
+ const rejectNils = R.compose(R.path([index]), R.filter(isNotNil));
42
29
 
43
- export const memoizedGetPluginIdentifier = memoizee(getPluginIdentifier);
30
+ return rejectNils(
31
+ R.toPairs(configuration)
32
+ .filter(([key]) => R.startsWith(`${prefix}_button`, key))
33
+ .map(([key, value]) => {
34
+ const matched = key.match(re);
35
+
36
+ return matched ? value : undefined;
37
+ })
38
+ );
39
+ };
44
40
 
45
41
  type Label = {
46
42
  name: string;
@@ -6,11 +6,16 @@ import { getPathAttributes } from "@applicaster/zapp-react-native-utils/navigati
6
6
  import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup";
7
7
  import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
8
8
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
9
+ import { StyleSheet } from "react-native";
9
10
 
10
11
  import { Screen } from "../Screen/TV/index.web";
11
12
  import { isLast } from "@applicaster/zapp-react-native-utils/arrayUtils";
12
13
  import { ScreenContextProvider } from "../../Contexts/ScreenContext";
13
14
 
15
+ const styles = StyleSheet.create({
16
+ container: { flex: 1 },
17
+ });
18
+
14
19
  type Components = {
15
20
  NavBar: React.ComponentType<any>;
16
21
  Background: React.ComponentType<any>;
@@ -41,6 +46,7 @@ export const StackNavigator = ({ Components }: Props) => {
41
46
  preferredFocus={isLast(index, mainStack.length)}
42
47
  excludeFromFocusSearching
43
48
  key={routeId}
49
+ style={styles.container}
44
50
  >
45
51
  <ScreenDataContext.Provider value={state}>
46
52
  <PathnameContext.Provider value={route}>
@@ -8,7 +8,7 @@ import {
8
8
  TouchableWithoutFeedback,
9
9
  } from "react-native";
10
10
 
11
- import { usePlugins } from "@applicaster/zapp-react-native-redux";
11
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
12
12
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
13
13
  import { textTransform } from "@applicaster/zapp-react-native-utils/cellUtils";
14
14
  import { useNotificationHeight } from "../utils";
@@ -46,7 +46,7 @@ export const NotificationView = ({
46
46
  online = true,
47
47
  dismiss,
48
48
  }: Props) => {
49
- const plugins = usePlugins();
49
+ const { plugins } = usePickFromState(["plugins"]);
50
50
  const { statusHeight, notificationHeight } = useNotificationHeight();
51
51
 
52
52
  const offlinePlugin = R.find(
@@ -8,24 +8,25 @@ import {
8
8
  offlinePhrase,
9
9
  } from "../NotificationView";
10
10
 
11
- jest.mock("@applicaster/zapp-react-native-redux", () => ({
12
- ...jest.requireActual("@applicaster/zapp-react-native-redux"),
13
- usePlugins: () => [
14
- {
15
- name: "offline experience",
16
- identifier: "offline-experience",
17
- type: "general",
18
- module: {
19
- useOfflineExperienceConfiguration: () => ({
20
- configurationFields: {},
21
- localizations: {
22
- offline_toast_message: "No internet connection",
23
- online_toast_message: "You are back online",
24
- },
25
- }),
11
+ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
12
+ usePickFromState: () => ({
13
+ plugins: [
14
+ {
15
+ name: "offline experience",
16
+ identifier: "offline-experience",
17
+ type: "general",
18
+ module: {
19
+ useOfflineExperienceConfiguration: () => ({
20
+ configurationFields: {},
21
+ localizations: {
22
+ offline_toast_message: "No internet connection",
23
+ online_toast_message: "You are back online",
24
+ },
25
+ }),
26
+ },
26
27
  },
27
- },
28
- ],
28
+ ],
29
+ }),
29
30
  }));
30
31
 
31
32
  jest.mock("react-native-safe-area-context", () => ({
@@ -8,45 +8,36 @@ const mockPreviousValue = null;
8
8
 
9
9
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => {
10
10
  return {
11
- ...jest.requireActual(
12
- "@applicaster/zapp-react-native-utils/reactHooks/connection"
13
- ),
14
11
  useConnectionInfo: jest.fn(() => mockConnectionStatus),
15
12
  };
16
13
  });
17
14
 
18
15
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/utils", () => {
19
16
  return {
20
- ...jest.requireActual(
21
- "@applicaster/zapp-react-native-utils/reactHooks/utils"
22
- ),
23
17
  usePrevious: jest.fn(() => mockPreviousValue),
24
18
  };
25
19
  });
26
20
 
27
- const mock_storeObj = {
28
- plugins: [
29
- {
30
- name: "offline experience",
31
- identifier: "offline-experience",
32
- type: "general",
33
- module: {
34
- useOfflineExperienceConfiguration: () => ({
35
- configurationFields: {},
36
- localizations: {
37
- offline_toast_message: "No internet connection",
38
- online_toast_message: "You are back online",
39
- },
40
- }),
41
- },
42
- },
43
- ],
44
- };
45
-
46
21
  jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
47
22
  ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
48
- usePlugins: () => mock_storeObj.plugins,
49
- usePickFromState: () => ({}),
23
+ usePickFromState: () => ({
24
+ plugins: [
25
+ {
26
+ name: "offline experience",
27
+ identifier: "offline-experience",
28
+ type: "general",
29
+ module: {
30
+ useOfflineExperienceConfiguration: () => ({
31
+ configurationFields: {},
32
+ localizations: {
33
+ offline_toast_message: "No internet connection",
34
+ online_toast_message: "You are back online",
35
+ },
36
+ }),
37
+ },
38
+ },
39
+ ],
40
+ }),
50
41
  }));
51
42
 
52
43
  jest.mock("react-native-safe-area-context", () => ({
@@ -17,7 +17,7 @@ import {
17
17
 
18
18
  import { TVEventHandlerComponent } from "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent";
19
19
  import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
20
-
20
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
21
21
  import {
22
22
  useBackHandler,
23
23
  useNavigation,
@@ -46,7 +46,6 @@ import {
46
46
  PlayerContainerContextProvider,
47
47
  } from "./PlayerContainerContext";
48
48
  import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup";
49
- import { ErrorDisplay } from "./ErrorDisplay";
50
49
  import { PlayerFocusableWrapperView } from "./WappersView/PlayerFocusableWrapperView";
51
50
  import { FocusableGroupMainContainerId } from "./index";
52
51
  import { isPlayable } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypeMatchers";
@@ -60,8 +59,6 @@ import {
60
59
  PlayerNativeCommandTypes,
61
60
  PlayerNativeSendCommand,
62
61
  } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerNativeCommand";
63
- import { useAppData } from "@applicaster/zapp-react-native-redux";
64
- import { useRestrictMobilePlayback } from "./useRestrictMobilePlayback";
65
62
 
66
63
  type Props = {
67
64
  Player: React.ComponentType<any>;
@@ -111,7 +108,7 @@ const withBorderHack = () => {
111
108
  /* @HACK: see GH#7269 */
112
109
  return {
113
110
  borderWidth: 1,
114
- borderColor: "transparent",
111
+ borderColor: "black",
115
112
  };
116
113
  }
117
114
 
@@ -240,7 +237,7 @@ const PlayerContainerComponent = (props: Props) => {
240
237
  const [isLoadingNextVideo, setIsLoadingNextVideo] = React.useState(false);
241
238
 
242
239
  const navigator = useNavigation();
243
- const { isTabletPortrait } = useAppData();
240
+ const { appData } = usePickFromState(["appData"]);
244
241
  const prevItemId = usePrevious(item?.id);
245
242
  const screenData = useTargetScreenData(item);
246
243
  const { setVisible: showNavBar } = useSetNavbarState();
@@ -265,21 +262,7 @@ const PlayerContainerComponent = (props: Props) => {
265
262
 
266
263
  showNavBar(true);
267
264
  navigator.goBack();
268
- }, [isModal, state.playerId, showNavBar, navigator]);
269
-
270
- const pluginConfiguration = React.useMemo(() => {
271
- return (
272
- playerManager.getPluginConfiguration() ||
273
- R.prop("__plugin_configuration", Player)
274
- );
275
- }, [playerManager.isRegistered()]);
276
-
277
- const { isRestricted } = useRestrictMobilePlayback({
278
- player,
279
- entry: item,
280
- pluginConfiguration,
281
- close,
282
- });
265
+ }, [isModal, navigator.goBack, state.playerId, showNavBar]);
283
266
 
284
267
  const playEntry = (entry) => navigator.replaceTop(entry, { mode });
285
268
 
@@ -347,12 +330,6 @@ const PlayerContainerComponent = (props: Props) => {
347
330
  playerContainerLogger.error(errorObj);
348
331
 
349
332
  setState({ error: errorObj });
350
-
351
- if (!isTvOS) {
352
- setTimeout(() => {
353
- close();
354
- }, 800);
355
- }
356
333
  },
357
334
  [close]
358
335
  );
@@ -471,6 +448,13 @@ const PlayerContainerComponent = (props: Props) => {
471
448
  }
472
449
  }, []);
473
450
 
451
+ const pluginConfiguration = React.useMemo(() => {
452
+ return (
453
+ playerManager.getPluginConfiguration() ||
454
+ R.prop("__plugin_configuration", Player)
455
+ );
456
+ }, [playerManager.isRegistered()]);
457
+
474
458
  const disableMiniPlayer = React.useMemo(() => {
475
459
  return pluginConfiguration?.disable_mini_player_when_inline;
476
460
  }, [pluginConfiguration]);
@@ -670,7 +654,7 @@ const PlayerContainerComponent = (props: Props) => {
670
654
  <PlayerFocusableWrapperView
671
655
  nextFocusDown={context.bottomFocusableId}
672
656
  >
673
- {isRestricted ? null : (
657
+ {Player ? (
674
658
  <Player
675
659
  source={{
676
660
  uri,
@@ -685,7 +669,7 @@ const PlayerContainerComponent = (props: Props) => {
685
669
  fullscreen={mode === VideoModalMode.FULLSCREEN}
686
670
  inline={inline}
687
671
  isModal={isModal}
688
- isTabletPortrait={isTabletPortrait}
672
+ isTabletPortrait={appData.isTabletPortrait}
689
673
  muted={false}
690
674
  playableItem={item}
691
675
  playerEvent={playerEvent}
@@ -701,10 +685,8 @@ const PlayerContainerComponent = (props: Props) => {
701
685
  >
702
686
  {renderApplePlayer(applePlayerProps)}
703
687
  </Player>
704
- )}
688
+ ) : null}
705
689
  </PlayerFocusableWrapperView>
706
-
707
- {state.error ? <ErrorDisplay error={state.error} /> : null}
708
690
  </View>
709
691
  {/* Components container */}
710
692
  {isInlineTV && context.showComponentsContainer ? (
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import { Text } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+ import { PreloaderWrapper } from "..";
5
+
6
+ describe("PreloaderWrapper", () => {
7
+ it("renders children when preloader is hidden", () => {
8
+ const { getByText } = render(
9
+ <PreloaderWrapper showPreloader={false}>
10
+ <Text>content</Text>
11
+ </PreloaderWrapper>
12
+ );
13
+
14
+ expect(getByText("content")).toBeDefined();
15
+ });
16
+
17
+ it("renders null when preloader is shown", () => {
18
+ const { queryByText } = render(
19
+ <PreloaderWrapper showPreloader>
20
+ <Text>content</Text>
21
+ </PreloaderWrapper>
22
+ );
23
+
24
+ expect(queryByText("content")).toBeNull();
25
+ });
26
+ });
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+
3
+ type PreloaderWrapperProps = {
4
+ showPreloader?: boolean;
5
+ children?: React.ReactNode;
6
+ };
7
+
8
+ export const PreloaderWrapper: React.FC<PreloaderWrapperProps> = ({
9
+ showPreloader = false,
10
+ children,
11
+ }) => {
12
+ return !showPreloader ? children : null;
13
+ };
14
+
15
+ export default PreloaderWrapper;
@@ -281,7 +281,6 @@ function ComponentsMapComponent(props: Props) {
281
281
  >
282
282
  <ViewportTracker>
283
283
  <FlatList
284
- testID="components-map-flat-list"
285
284
  ref={(ref) => {
286
285
  flatListRef.current = ref;
287
286
  }}
@@ -313,10 +312,10 @@ function ComponentsMapComponent(props: Props) {
313
312
  onScrollEndDrag={_onScrollEndDrag}
314
313
  scrollEventThrottle={16}
315
314
  {...scrollViewExtraProps}
315
+ /* When wrapped in a parent ScrollView (e.g. tabs),
316
+ this FlatList doesn't scroll so onEndReached can fire repeatedly;
317
+ skip it here and let the parent ScrollView emit scroll-end instead. */
316
318
  onEndReached={
317
- /* When wrapped in a parent ScrollView (e.g. tabs),
318
- this FlatList doesn't scroll so onEndReached can fire repeatedly;
319
- skip it here and let the parent ScrollView emit scroll-end instead. */
320
319
  isScreenWrappedInContainer
321
320
  ? undefined
322
321
  : () => {