@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3977160850 → 12.0.0-alpha.4043183114

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 (113) hide show
  1. package/Components/BaseFocusable/index.tsx +3 -3
  2. package/Components/Cell/Cell.tsx +16 -15
  3. package/Components/Cell/CellWithFocusable.tsx +40 -19
  4. package/Components/Cell/TvOSCellComponent.tsx +8 -13
  5. package/Components/ErrorScreen/index.tsx +1 -1
  6. package/Components/Focusable/Focusable.tsx +6 -1
  7. package/Components/FocusableCell/index.tsx +7 -7
  8. package/Components/FocusableGroup/index.tsx +11 -2
  9. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  10. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  11. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  12. package/Components/HookRenderer/index.tsx +1 -3
  13. package/Components/Image/Image.android.tsx +3 -25
  14. package/Components/Image/Image.tsx +18 -2
  15. package/Components/Image/utils/index.ts +39 -0
  16. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  17. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  18. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  19. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  20. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -10
  21. package/Components/Layout/TV/__tests__/index.test.tsx +20 -87
  22. package/Components/Layout/TV/index.tsx +14 -67
  23. package/Components/Layout/TV/index.web.tsx +33 -0
  24. package/Components/Layout/index.tsx +15 -11
  25. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  26. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -112
  27. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  28. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  29. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
  30. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  31. package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
  32. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  33. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +37 -2
  34. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
  35. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  36. package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
  37. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  38. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  39. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  40. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  41. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  42. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  43. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  44. package/Components/MasterCell/utils/index.ts +35 -37
  45. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  46. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  47. package/Components/NativeFocusables/{index.js → index.ts} +4 -2
  48. package/Components/Navigator/StackNavigator.tsx +57 -0
  49. package/Components/Navigator/index.ts +1 -0
  50. package/Components/PlayerContainer/PlayerContainer.tsx +66 -31
  51. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
  52. package/Components/PlayerImageBackground/index.tsx +34 -8
  53. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  54. package/Components/River/RefreshControl.tsx +55 -1
  55. package/Components/River/TV/River.tsx +0 -23
  56. package/Components/River/__tests__/componentsMap.test.js +7 -0
  57. package/Components/Screen/TV/hooks/index.ts +3 -0
  58. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  59. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  60. package/Components/Screen/TV/index.web.tsx +165 -0
  61. package/Components/Screen/__tests__/Screen.test.tsx +8 -1
  62. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +14 -0
  63. package/Components/Screen/index.tsx +65 -48
  64. package/Components/Screen/navigationHandler.ts +5 -0
  65. package/Components/ScreenResolver/index.tsx +3 -1
  66. package/Components/Tabs/TV/styles.ts +1 -1
  67. package/Components/Transitioner/Scene.tsx +32 -26
  68. package/Components/Transitioner/Transitioner.tsx +21 -28
  69. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  70. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  71. package/Components/VideoLive/LiveImageManager.ts +28 -1
  72. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -28
  73. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
  74. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
  75. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +66 -0
  76. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +355 -0
  77. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +161 -0
  78. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +456 -0
  79. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +182 -0
  80. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  81. package/Components/VideoModal/ModalAnimation/utils.ts +302 -0
  82. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  83. package/Components/VideoModal/PlayerWrapper.tsx +77 -47
  84. package/Components/VideoModal/VideoModal.tsx +23 -40
  85. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
  86. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +266 -166
  87. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  88. package/Components/VideoModal/utils.ts +8 -5
  89. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  90. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  91. package/Components/Viewport/utils.js +1 -1
  92. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  93. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  94. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  95. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  96. package/Contexts/FocusableGroupContext/index.ts +7 -0
  97. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  98. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  99. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  100. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  101. package/Contexts/ScreenContext/index.tsx +94 -25
  102. package/Contexts/ScreenDataContext/index.tsx +20 -0
  103. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  104. package/Decorators/Analytics/{index.js → index.tsx} +11 -11
  105. package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
  106. package/README.md +1 -13
  107. package/events/index.ts +1 -0
  108. package/package.json +5 -5
  109. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  110. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  111. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  112. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  113. /package/Contexts/{index.js → index.ts} +0 -0
@@ -66,14 +66,14 @@ export class BaseFocusable<
66
66
  const { initialFocus } = this.props;
67
67
 
68
68
  if (initialFocus) {
69
- focusManager.setupInitialFocus(this.getId());
69
+ focusManager.setFocus(this.getId());
70
70
  }
71
71
  }
72
72
 
73
73
  getId(props?: { id: string; groupId: string }) {
74
- const { id, groupId = null } = props || this.props;
74
+ const { id } = props || this.props;
75
75
 
76
- return groupId ? `${groupId}-${id}` : id;
76
+ return id;
77
77
  }
78
78
 
79
79
  getRect() {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
2
+ import { join, path, merge } from "ramda";
3
3
  import { View } from "react-native";
4
4
 
5
5
  import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
@@ -11,12 +11,10 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
11
11
 
12
12
  import { CellWithFocusable } from "./CellWithFocusable";
13
13
  import { BaseFocusable } from "../BaseFocusable";
14
+ import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
14
15
 
15
16
  type Props = {
16
- item: {
17
- id: string;
18
- title: string;
19
- };
17
+ item: ZappEntry;
20
18
  index: number;
21
19
  shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
22
20
  shouldScrollVertically: (...args: any) => boolean | null | undefined;
@@ -32,10 +30,9 @@ type Props = {
32
30
  id: string;
33
31
  };
34
32
  selected?: boolean;
35
- CellRenderer: React.ComponentType<{
36
- item: any;
37
- state: string;
38
- }> & { hasFocusableInside: (item: Record<string, string>) => boolean };
33
+ CellRenderer: React.FunctionComponent<any> & {
34
+ hasFocusableInside: (item: ZappEntry) => boolean;
35
+ };
39
36
  preferredFocus: boolean;
40
37
  navigator: {
41
38
  push: (arg1: Record<any, any>) => void;
@@ -105,8 +102,8 @@ export class CellComponent extends React.Component<Props> {
105
102
  onPress(item, index);
106
103
  } else {
107
104
  const { item, navigator, component, appData } = this.props;
108
- const itemTargetScreen = R.path(["screen_type"], item);
109
- const componentTargetScreen = R.path(["data", "target"], component);
105
+ const itemTargetScreen = path(["screen_type"], item);
106
+ const componentTargetScreen = path(["data", "target"], component);
110
107
  const itemType = getItemType(item, appData?.layoutVersion);
111
108
 
112
109
  sendSelectCellEvent(item, component, item.title, index);
@@ -116,7 +113,7 @@ export class CellComponent extends React.Component<Props> {
116
113
  componentTargetScreen &&
117
114
  !itemTargetScreen
118
115
  ) {
119
- navigator.push(R.merge(item, { screen_type: componentTargetScreen }));
116
+ navigator.push(merge(item, { screen_type: componentTargetScreen }));
120
117
 
121
118
  return;
122
119
  }
@@ -139,6 +136,10 @@ export class CellComponent extends React.Component<Props> {
139
136
  shouldScrollVertically?.(mouse, focusable, id, title)
140
137
  ) {
141
138
  this.scrollVertically(focusable);
139
+
140
+ const accessibilityManager = AccessibilityManager.getInstance();
141
+ // Text from DSP should be localized already
142
+ accessibilityManager.readText({ text: title.toString() });
142
143
  }
143
144
  }
144
145
  }
@@ -202,12 +203,12 @@ export class CellComponent extends React.Component<Props> {
202
203
  groupId,
203
204
  isFocusable = true,
204
205
  skipFocusManagerRegistration,
205
- behavior
206
+ behavior,
206
207
  } = this.props;
207
208
 
208
209
  const { id } = item;
209
210
 
210
- const focusableId = R.join("-", [component?.id, id, index]);
211
+ const focusableId = join("-", [component?.id, id, index]);
211
212
 
212
213
  const handleFocus = (focusable, mouse) => {
213
214
  const focusFn = onFocus || noop;
@@ -263,7 +264,7 @@ export class CellComponent extends React.Component<Props> {
263
264
  item,
264
265
  focused: this.isCellFocused(focused),
265
266
  scrollTo: this.scrollToIndex(event),
266
- behavior
267
+ behavior,
267
268
  }}
268
269
  />
269
270
  );
@@ -3,15 +3,25 @@ import * as React from "react";
3
3
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
4
4
  import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
5
5
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
6
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
7
+
6
8
  import { isAppleTV } from "../../Helpers/Platform";
7
9
  import { useCellState } from "../MasterCell/utils";
8
10
 
9
- const useCellFocusedState = (groupId: string, id: string) => {
11
+ const useCellFocusedState = (
12
+ skipFocusManagerRegistration: boolean,
13
+ groupId: string,
14
+ id: string
15
+ ) => {
10
16
  const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
11
17
 
12
18
  React.useEffect(() => {
13
- const isGroupItemFocused = () =>
14
- setCurrentCellFocused(focusManager.isGroupItemFocused(groupId, id));
19
+ const isGroupItemFocused = () => {
20
+ if (!skipFocusManagerRegistration) {
21
+ const isFocused = focusManager.isGroupItemFocused(groupId, id);
22
+ setCurrentCellFocused(isFocused);
23
+ }
24
+ };
15
25
 
16
26
  const handler = () => {
17
27
  // tvOS hack for properly checking focus
@@ -29,24 +39,24 @@ const useCellFocusedState = (groupId: string, id: string) => {
29
39
  return () => {
30
40
  focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
31
41
  };
32
- }, [groupId]);
42
+ }, [groupId, skipFocusManagerRegistration]);
33
43
 
34
44
  return currentCellFocused;
35
45
  };
36
46
 
37
47
  type Props = {
38
- item: ZappEntry,
39
- CellRenderer: React.ComponentType<{ item: Object, state: string }>,
40
- id: string,
41
- groupId: string,
42
- onFocus: Function,
43
- index: number,
44
- scrollTo: Function,
45
- preferredFocus?: boolean,
46
- skipFocusManagerRegistration?: boolean,
47
- isFocusable?: boolean,
48
- behavior: Behavior,
49
- selected?: boolean,
48
+ item: ZappEntry;
49
+ CellRenderer: React.FunctionComponent<any>;
50
+ id: string;
51
+ groupId: string;
52
+ onFocus: Function;
53
+ index: number;
54
+ scrollTo: Function;
55
+ preferredFocus?: boolean;
56
+ skipFocusManagerRegistration?: boolean;
57
+ isFocusable?: boolean;
58
+ behavior: Behavior;
59
+ focused?: boolean;
50
60
  };
51
61
 
52
62
  export function CellWithFocusable(props: Props) {
@@ -62,11 +72,21 @@ export function CellWithFocusable(props: Props) {
62
72
  skipFocusManagerRegistration,
63
73
  isFocusable,
64
74
  behavior,
65
- selected
75
+ focused,
66
76
  } = props;
67
77
 
68
- const isFocused = useCellFocusedState(groupId, id);
69
- const state = useCellState({ id: item.id, behavior, focused: isFocused, selected });
78
+ const isFocused = useCellFocusedState(
79
+ skipFocusManagerRegistration,
80
+ groupId,
81
+ id
82
+ );
83
+
84
+ const state = useCellState({
85
+ id: item.id,
86
+ behavior,
87
+ focused: isFocused || toBooleanWithDefaultFalse(focused),
88
+ });
89
+
70
90
  const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);
71
91
 
72
92
  // for horizontal scrolling
@@ -95,6 +115,7 @@ export function CellWithFocusable(props: Props) {
95
115
  preferredFocus={preferredFocus}
96
116
  skipFocusManagerRegistration={skipFocusManagerRegistration}
97
117
  isFocusable={isFocusable}
118
+ focused={focused}
98
119
  />
99
120
  );
100
121
  }
@@ -36,10 +36,9 @@ type Props = {
36
36
  component_type: string;
37
37
  };
38
38
  selected: boolean;
39
- CellRenderer: React.ComponentType<{
40
- item: any;
41
- state: string;
42
- }> & { hasFocusableInside: (item: any) => boolean };
39
+ CellRenderer: React.FunctionComponent<any> & {
40
+ hasFocusableInside: (item: any) => boolean;
41
+ };
43
42
  preferredFocus: boolean;
44
43
  navigator: {
45
44
  push: (arg1: Record<any, any>) => void;
@@ -226,13 +225,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
226
225
 
227
226
  hasReceivedFocus() {}
228
227
 
229
- scrollTo(index) {
230
- // Workaround for HL autoscroll/autoloop feature, we scroll manually on tvOS.
231
- // Should be removed after refactoring autoscroll/autoloop feature
232
- if (this.props.component?.component_type !== "horizontal_list_qb") {
233
- this.props?.scrollToIndex?.(index);
234
- }
235
- }
228
+ scrollTo() {}
236
229
 
237
230
  render() {
238
231
  const {
@@ -249,7 +242,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
249
242
  hasReceivedFocus,
250
243
  groupId,
251
244
  isFocusable,
252
- behavior
245
+ behavior,
253
246
  } = this.props;
254
247
 
255
248
  const { id } = item;
@@ -279,7 +272,9 @@ export class TvOSCellComponent extends React.Component<Props, State> {
279
272
  index={index}
280
273
  scrollTo={this.scrollTo}
281
274
  preferredFocus={preferredFocus}
275
+ focused={this.props.focused}
282
276
  behavior={behavior}
277
+ isFocusable={isFocusable}
283
278
  />
284
279
  </View>
285
280
  );
@@ -310,7 +305,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
310
305
  item,
311
306
  focused: this.props.focused || selectedCell || focused,
312
307
  scrollTo: this.scrollTo,
313
- behavior
308
+ behavior,
314
309
  }}
315
310
  />
316
311
  );
@@ -3,7 +3,6 @@ import * as R from "ramda";
3
3
  import {
4
4
  View,
5
5
  StyleSheet,
6
- Image,
7
6
  Text,
8
7
  ViewStyle,
9
8
  TextStyle,
@@ -13,6 +12,7 @@ import {
13
12
  import { defaultAsset } from "./defaultAsset";
14
13
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
15
14
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
15
+ import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
16
16
  import { Button } from "./Button";
17
17
 
18
18
  type ButtonProp = {
@@ -4,6 +4,7 @@ import * as R from "ramda";
4
4
  import { BaseFocusable } from "../BaseFocusable";
5
5
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
6
6
  import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
7
+ import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
7
8
 
8
9
  type Props = {
9
10
  initialFocus?: boolean;
@@ -23,7 +24,7 @@ type Props = {
23
24
  style?: React.CSSProperties;
24
25
  };
25
26
 
26
- export class Focusable extends BaseFocusable<Props> {
27
+ class Focusable extends BaseFocusable<Props> {
27
28
  isGroup: boolean;
28
29
  mouse: boolean;
29
30
  longPressTimeout = null;
@@ -198,3 +199,7 @@ export class Focusable extends BaseFocusable<Props> {
198
199
  );
199
200
  }
200
201
  }
202
+
203
+ const FocusableWithFocusableContext = withFocusableContext(Focusable);
204
+
205
+ export { FocusableWithFocusableContext as Focusable };
@@ -3,12 +3,12 @@ import { Platform } from "react-native";
3
3
  import { useCellState } from "../MasterCell/utils";
4
4
 
5
5
  type Props = {
6
- index: number,
7
- item: ZappEntry,
8
- focused: boolean,
9
- scrollTo?: (index: number) => void,
10
- CellRenderer: React.ComponentType<{ item: Object, state: string }>,
11
- behavior: Behavior
6
+ index: number;
7
+ item: ZappEntry;
8
+ focused: boolean;
9
+ scrollTo?: (index: number) => void;
10
+ CellRenderer: React.ComponentType<{ item: Object; state: string }>;
11
+ behavior: Behavior;
12
12
  };
13
13
 
14
14
  const isAndroid = Platform.OS === "android";
@@ -20,7 +20,7 @@ export function FocusableCell(props: Props) {
20
20
  CellRenderer,
21
21
  focused,
22
22
  scrollTo = null,
23
- behavior
23
+ behavior,
24
24
  } = props;
25
25
 
26
26
  const state = useCellState({ id: item.id, behavior, focused });
@@ -1,6 +1,8 @@
1
1
  import * as React from "react";
2
2
 
3
3
  import { BaseFocusable } from "../BaseFocusable";
4
+ import { FocusableGroupContextProvider } from "../../Contexts/FocusableGroupContext";
5
+ import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
4
6
 
5
7
  type Props = {
6
8
  testID?: string;
@@ -26,9 +28,10 @@ type Props = {
26
28
  nextFocusLeft?: any;
27
29
  nextFocusRight?: any;
28
30
  onLayout?: any;
31
+ excludeFromFocusSearching?: boolean;
29
32
  };
30
33
 
31
- export class FocusableGroup extends BaseFocusable<Props> {
34
+ class FocusableGroup extends BaseFocusable<Props> {
32
35
  constructor(props) {
33
36
  super(props);
34
37
  this.isGroup = true;
@@ -81,8 +84,14 @@ export class FocusableGroup extends BaseFocusable<Props> {
81
84
  style={style}
82
85
  ref={this.ref}
83
86
  >
84
- {children}
87
+ <FocusableGroupContextProvider id={id}>
88
+ {children}
89
+ </FocusableGroupContextProvider>
85
90
  </div>
86
91
  );
87
92
  }
88
93
  }
94
+
95
+ const FocusableGroupWithFocusableContext = withFocusableContext(FocusableGroup);
96
+
97
+ export { FocusableGroupWithFocusableContext as FocusableGroup };
@@ -50,7 +50,11 @@ describe("getTransformedPreset should return the passed components if smartCompo
50
50
  );
51
51
 
52
52
  expect(transformed_preset).toBeDefined();
53
- expect(transformed_preset.id).toEqual("comp10"); // id was transformed
53
+
54
+ expect(transformed_preset.id).toEqual(
55
+ `${mockComp.id}-${mockPreset.feed_url}-0`
56
+ ); // id was transformed
57
+
54
58
  expect(transformed_preset.data.source).toEqual(mockPreset.feed_url); // source was replaced with preset feed_url.
55
59
  });
56
60
  });
@@ -117,7 +121,10 @@ describe("getTransformedPreset should return the passed components if smartCompo
117
121
 
118
122
  expect(Array.isArray(result)).toBe(true);
119
123
  expect(result).toHaveLength(2);
120
- expect(result[0].id).toEqual("smart10");
124
+
125
+ expect(result[0].id).toEqual(
126
+ `${mockSmartComp.id}-${mockFeeds.preset_source.data.entry[0].feed_url}-0`
127
+ );
121
128
 
122
129
  expect(result[0].data.source).toEqual(
123
130
  mockFeeds.preset_source.data.entry[0].feed_url
@@ -287,7 +294,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
287
294
  mockComponents[0],
288
295
  {
289
296
  ...mockLayoutPresets.preset_one,
290
- id: mockComponents[1].id + 1,
297
+ id: `${mockComponents[1].id}-${mockPresetEntry[0].feed_url}-1`,
291
298
  data: { source: mockPresetEntry[0].feed_url },
292
299
  },
293
300
  ];
@@ -344,12 +351,12 @@ describe("getTransformedPreset should return the passed components if smartCompo
344
351
  const mockTransformedComponents = [
345
352
  {
346
353
  ...mockLayoutPresets.preset_one,
347
- id: mockComponents[0].id + 0,
354
+ id: `${mockComponents[0].id}-${mockPresetEntry1[0].feed_url}-0`,
348
355
  data: { source: mockPresetEntry1[0].feed_url },
349
356
  },
350
357
  {
351
358
  ...mockLayoutPresets.preset_one,
352
- id: mockComponents[1].id + 1,
359
+ id: `${mockComponents[1].id}-${mockPresetEntry2[0].feed_url}-1`,
353
360
  data: { source: mockPresetEntry2[0].feed_url },
354
361
  },
355
362
  ];
@@ -412,7 +419,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
412
419
  const mockTransformedComponents = mockPresetEntry.map((preset, i) => {
413
420
  return {
414
421
  ...mockLayoutPresets[preset.preset_name],
415
- id: mockComponents[0].id + i,
422
+ id: `${mockComponents[0].id}-${preset.feed_url}-${i}`,
416
423
  data: { source: preset.feed_url },
417
424
  };
418
425
  });
@@ -41,7 +41,7 @@ export const getTransformedPreset = (
41
41
  }
42
42
 
43
43
  const updatedPresetComponent = produce(presetComponent, (draft) => {
44
- draft.id = `${componentId}${index}`;
44
+ draft.id = `${componentId}-${preset?.feed_url}-${index}`;
45
45
  draft.data.source = preset?.feed_url;
46
46
 
47
47
  if (draft.ui_components) {
@@ -19,6 +19,7 @@ type Props = {
19
19
  modalHeight?: number;
20
20
  modalWidth?: number;
21
21
  mode: VideoModalMode;
22
+ groupId?: string;
22
23
  };
23
24
 
24
25
  const YOUTUBE_PLUGIN_ID = "youtube-player-qb";
@@ -93,6 +94,7 @@ export function HandlePlayable({
93
94
  modalHeight,
94
95
  modalWidth,
95
96
  mode,
97
+ groupId,
96
98
  }: Props): React.ReactElement | null {
97
99
  const state = usePickFromState();
98
100
 
@@ -167,6 +169,7 @@ export function HandlePlayable({
167
169
  isModal={isModal}
168
170
  mode={mode}
169
171
  disableCastAction={playerModuleProperties?.disableCastAction}
172
+ groupId={groupId}
170
173
  />
171
174
  );
172
175
  }
@@ -1,3 +1 @@
1
- import { HookRenderer as HookRendererComponent } from "./HookRenderer";
2
-
3
- export const HookRenderer = HookRendererComponent;
1
+ export { HookRenderer } from "./HookRenderer";
@@ -3,32 +3,10 @@ import FastImage, {
3
3
  FastImageProps,
4
4
  } from "@applicaster/react-native-fast-image";
5
5
 
6
- export const QBImage = (props: FastImageProps) => {
7
- const source = React.useMemo(() => {
8
- if (typeof props.source === "number") {
9
- return props.source;
10
- }
6
+ import { useImageSource } from "./utils";
11
7
 
12
- return {
13
- uri: props.source.uri,
14
- headers: props.source.headers,
15
- priority: props.source.priority,
16
- cache: props.source.cache,
17
- maxWidth: props.source.maxWidth,
18
- maxHeight: props.source.maxHeight,
19
- };
20
- }, [
21
- ...(typeof props.source === "object"
22
- ? [
23
- props.source?.uri,
24
- props.source?.priority,
25
- props.source?.cache,
26
- props.source?.headers,
27
- props.source?.maxWidth,
28
- props.source?.maxHeight,
29
- ]
30
- : []),
31
- ]);
8
+ export const QBImage = (props: FastImageProps) => {
9
+ const source = useImageSource(props.source);
32
10
 
33
11
  return <FastImage {...props} source={source} />;
34
12
  };
@@ -1,8 +1,24 @@
1
- import { Image, ImageProps, ImageStyle, StyleProp } from "react-native";
1
+ import React from "react";
2
+ import {
3
+ Image,
4
+ ImageBackground,
5
+ ImageProps,
6
+ ImageStyle,
7
+ StyleProp,
8
+ } from "react-native";
2
9
 
3
10
  export interface Props extends ImageProps {
4
11
  style?: StyleProp<ImageStyle> | undefined;
5
12
  }
6
13
 
7
14
  // TODO - React.FC<Props> QBImage should process incoming url and apply any transformations if needed
8
- export const QBImage = Image;
15
+ export const QBImage = ({
16
+ children,
17
+ ...props
18
+ }: Props & { children?: React.ReactNode }) => {
19
+ if (children) {
20
+ return <ImageBackground {...props}>{children}</ImageBackground>;
21
+ }
22
+
23
+ return <Image {...props} />;
24
+ };
@@ -0,0 +1,39 @@
1
+ import FastImage, { Source } from "@applicaster/react-native-fast-image";
2
+ import { useMemo } from "react";
3
+ import { ImageRequireSource } from "react-native";
4
+
5
+ function getSourceCache(cache: Source["cache"]) {
6
+ return cache || FastImage.cacheControl.web;
7
+ }
8
+
9
+ export const useImageSource = (source?: Source | ImageRequireSource) => {
10
+ return useMemo(() => {
11
+ if (source) {
12
+ if (typeof source === "number") {
13
+ return source;
14
+ }
15
+
16
+ return {
17
+ uri: source.uri,
18
+ headers: source.headers,
19
+ priority: source.priority,
20
+ cache: getSourceCache(source?.cache),
21
+ maxWidth: source.maxWidth,
22
+ maxHeight: source.maxHeight,
23
+ };
24
+ }
25
+
26
+ return undefined;
27
+ }, [
28
+ ...(typeof source === "object"
29
+ ? [
30
+ source?.uri,
31
+ source?.priority,
32
+ source?.cache,
33
+ source?.headers,
34
+ source?.maxWidth,
35
+ source?.maxHeight,
36
+ ]
37
+ : []),
38
+ ]);
39
+ };