@applicaster/zapp-react-native-ui-components 16.0.0-rc.4 → 16.0.0-rc.40
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.
- package/Components/BackgroundImage/BackgroundImage.android.tv.tsx +28 -0
- package/Components/BackgroundImage/BackgroundImage.ios.tv.tsx +24 -0
- package/Components/BackgroundImage/BackgroundImage.tsx +42 -0
- package/Components/BackgroundImage/index.ts +1 -0
- package/Components/CellRendererResolver/index.ts +2 -2
- package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
- package/Components/FocusableGroup/FocusableTvOS.tsx +11 -7
- package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
- package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
- package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
- package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
- package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
- package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
- package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
- package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
- package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
- package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
- package/Components/GeneralContentScreen/index.ts +2 -0
- package/Components/Layout/FullWidthRow.tsx +38 -0
- package/Components/Layout/TV/ScreenContainer.tsx +5 -0
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +2 -3
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +47 -21
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +34 -6
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +29 -9
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -100
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +15 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +56 -22
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +6 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +3 -1
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +32 -21
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +15 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +23 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +8 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +2 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +2 -2
- package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
- package/Components/MasterCell/dataAdapter.ts +15 -5
- package/Components/MasterCell/hooks/index.ts +2 -0
- package/Components/MasterCell/hooks/usePressedState.ts +4 -0
- package/Components/MasterCell/index.tsx +30 -5
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +169 -132
- package/Components/MasterCell/utils/__tests__/resolveColorForProp.test.js +92 -0
- package/Components/MasterCell/utils/index.ts +85 -46
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +332 -0
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +402 -0
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +811 -0
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +878 -0
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +9 -0
- package/Components/ModalComponent/BottomSheetModalContent.tsx +34 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
- package/Components/OfflineHandler/__tests__/index.test.tsx +78 -18
- package/Components/OfflineHandler/hooks.ts +123 -0
- package/Components/OfflineHandler/index.tsx +51 -73
- package/Components/OfflineHandler/utils/index.ts +1 -13
- package/Components/PlayerContainer/PlayerContainer.tsx +14 -10
- package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +284 -0
- package/Components/PreloaderWrapper/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +2 -2
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +3 -15
- package/Components/Screen/TV/hooks/__tests__/useAfterPaint.test.ts +60 -0
- package/Components/Screen/TV/hooks/index.ts +2 -0
- package/Components/Screen/TV/hooks/useAfterPaint.ts +23 -0
- package/Components/Screen/TV/index.web.tsx +16 -7
- package/Components/Screen/index.tsx +8 -4
- package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
- package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
- package/Components/ScreenRevealManager/Overlay.tsx +34 -0
- package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +8 -19
- package/Components/TopCutoffOverlay/index.tsx +2 -2
- package/Components/Transitioner/Transitioner.tsx +28 -17
- package/Components/VideoLive/LiveImageManager.ts +56 -45
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +4 -2
- package/Components/VideoModal/utils.ts +6 -1
- package/Components/ZappFrameworkComponents/BarView/BarView.tsx +12 -5
- package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
- package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
- package/Contexts/CachedDimensionsContext/index.ts +17 -2
- package/Helpers/ComponentCellSelectionHelper/index.js +0 -6
- package/Helpers/index.js +7 -40
- package/package.json +5 -5
- package/Components/Layout/TV/LayoutBackground.tsx +0 -31
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -66
- package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
- package/Components/Screen/utils.ts +0 -16
- package/Helpers/Analytics/index.js +0 -95
- /package/Components/MasterCell/DefaultComponents/ButtonContainerView/{index.tv.android.tsx → index.android.tv.tsx} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Text as RNText,
|
|
2
|
+
import { Pressable, Text as RNText, View } from "react-native";
|
|
3
3
|
import { render, fireEvent } from "@testing-library/react-native";
|
|
4
4
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
5
|
|
|
@@ -8,6 +8,11 @@ import { elementMapper } from "../../../../elementMapper";
|
|
|
8
8
|
import { defaultComponents } from "../../../index";
|
|
9
9
|
import { MobileActionButtons } from "..";
|
|
10
10
|
import { AssetComponent } from "../AssetComponent";
|
|
11
|
+
import { usePressedState } from "../../../../hooks/usePressedState";
|
|
12
|
+
|
|
13
|
+
jest.mock("../../../../hooks/usePressedState", () => ({
|
|
14
|
+
usePressedState: jest.fn(),
|
|
15
|
+
}));
|
|
11
16
|
|
|
12
17
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/actions", () => ({
|
|
13
18
|
useActions: jest.fn(),
|
|
@@ -136,6 +141,7 @@ const baseNode = {
|
|
|
136
141
|
borderColor: "rgba(4,4,4,1)",
|
|
137
142
|
},
|
|
138
143
|
testID: "mobile-action-button",
|
|
144
|
+
testOnly_pressed: false,
|
|
139
145
|
},
|
|
140
146
|
elements: [
|
|
141
147
|
{
|
|
@@ -190,14 +196,20 @@ const baseNode = {
|
|
|
190
196
|
describe("MobileActionButton", () => {
|
|
191
197
|
beforeEach(() => {
|
|
192
198
|
jest.clearAllMocks();
|
|
199
|
+
(usePressedState as jest.Mock).mockReturnValue(false);
|
|
193
200
|
});
|
|
194
201
|
|
|
195
|
-
const renderNode = (node = baseNode) =>
|
|
196
|
-
|
|
202
|
+
const renderNode = ({ node = baseNode, pressed = false } = {}) => {
|
|
203
|
+
if (pressed) {
|
|
204
|
+
node.props.testOnly_pressed = true;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return render(
|
|
197
208
|
<React.Fragment>
|
|
198
209
|
{elementMapper(defaultComponents)(node as never)}
|
|
199
210
|
</React.Fragment>
|
|
200
211
|
);
|
|
212
|
+
};
|
|
201
213
|
|
|
202
214
|
it("renders nested image and text children through elementMapper", () => {
|
|
203
215
|
mockUseActions.mockReturnValue(buildActionContext());
|
|
@@ -210,12 +222,13 @@ describe("MobileActionButton", () => {
|
|
|
210
222
|
});
|
|
211
223
|
|
|
212
224
|
it("applies focused styles when action entry state is active", () => {
|
|
225
|
+
(usePressedState as jest.Mock).mockReturnValue(true);
|
|
213
226
|
mockUseActions.mockReturnValue(buildActionContext({ active: true }));
|
|
214
227
|
|
|
215
|
-
const { getByTestId, getByText } = renderNode();
|
|
228
|
+
const { getByTestId, getByText } = renderNode({ pressed: true });
|
|
216
229
|
|
|
217
230
|
expect(
|
|
218
|
-
getByTestId("mobile-action-button").props.style.backgroundColor
|
|
231
|
+
getByTestId("mobile-action-button").props.style[2].backgroundColor
|
|
219
232
|
).toBe("rgba(3,3,3,1)");
|
|
220
233
|
|
|
221
234
|
expect(getByText("Play").props.style).toEqual(
|
|
@@ -253,6 +266,8 @@ describe("MobileActionButton", () => {
|
|
|
253
266
|
})
|
|
254
267
|
);
|
|
255
268
|
|
|
269
|
+
node.props.testOnly_pressed = false;
|
|
270
|
+
|
|
256
271
|
const { UNSAFE_getAllByType, UNSAFE_getByType, getByTestId, getByText } =
|
|
257
272
|
render(
|
|
258
273
|
<React.Fragment>
|
|
@@ -260,14 +275,14 @@ describe("MobileActionButton", () => {
|
|
|
260
275
|
</React.Fragment>
|
|
261
276
|
);
|
|
262
277
|
|
|
263
|
-
const pressable = UNSAFE_getByType(
|
|
278
|
+
const pressable = UNSAFE_getByType(Pressable);
|
|
264
279
|
const label = getByText("Play");
|
|
265
280
|
const asset = getByTestId("mobile_action_button_1-asset");
|
|
266
281
|
|
|
267
282
|
expect(pressable.props.testID).toBe("mobile_action_button_1");
|
|
268
283
|
expect(pressable.props.accessibilityLabel).toBe("entry-1");
|
|
269
284
|
|
|
270
|
-
expect(pressable.props.style).toMatchObject({
|
|
285
|
+
expect(pressable.props.style({ pressed: false })[0]).toMatchObject({
|
|
271
286
|
backgroundColor: "rgba(1,1,1,1)",
|
|
272
287
|
borderColor: "rgba(2,2,2,1)",
|
|
273
288
|
borderWidth: 1,
|
|
@@ -278,15 +293,11 @@ describe("MobileActionButton", () => {
|
|
|
278
293
|
height: 24,
|
|
279
294
|
});
|
|
280
295
|
|
|
281
|
-
expect(label.props.style).
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
lineHeight: 24,
|
|
287
|
-
}),
|
|
288
|
-
])
|
|
289
|
-
);
|
|
296
|
+
expect(label.props.style[0]).toMatchObject({
|
|
297
|
+
color: "rgba(10,10,10,1)",
|
|
298
|
+
fontSize: 15,
|
|
299
|
+
lineHeight: 24,
|
|
300
|
+
});
|
|
290
301
|
|
|
291
302
|
expect(UNSAFE_getAllByType(View).length).toBeGreaterThan(0);
|
|
292
303
|
expect(UNSAFE_getAllByType(RNText).length).toBeGreaterThan(0);
|
|
@@ -324,7 +335,7 @@ describe("MobileActionButton", () => {
|
|
|
324
335
|
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
325
336
|
);
|
|
326
337
|
|
|
327
|
-
const { getByTestId } = renderNode(nodeWithFlavour1);
|
|
338
|
+
const { getByTestId } = renderNode({ node: nodeWithFlavour1 });
|
|
328
339
|
|
|
329
340
|
expect(MockAssetComponent).toHaveBeenCalled();
|
|
330
341
|
expect(getByTestId("mobile-action-button-asset")).toBeTruthy();
|
|
@@ -339,7 +350,7 @@ describe("MobileActionButton", () => {
|
|
|
339
350
|
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
340
351
|
);
|
|
341
352
|
|
|
342
|
-
renderNode(nodeWithFlavour1);
|
|
353
|
+
renderNode({ node: nodeWithFlavour1 });
|
|
343
354
|
|
|
344
355
|
expect(MockAssetComponent).toHaveBeenCalledWith(
|
|
345
356
|
expect.objectContaining({ flavour: "flavour_1" }),
|
|
@@ -356,7 +367,7 @@ describe("MobileActionButton", () => {
|
|
|
356
367
|
buildActionContext({ mobileButtonAssets: MockAssetComponent })
|
|
357
368
|
);
|
|
358
369
|
|
|
359
|
-
renderNode(nodeWithFlavour2);
|
|
370
|
+
renderNode({ node: nodeWithFlavour2 });
|
|
360
371
|
|
|
361
372
|
expect(MockAssetComponent).toHaveBeenCalledWith(
|
|
362
373
|
expect.objectContaining({ flavour: "flavour_2" }),
|
|
@@ -369,7 +380,7 @@ describe("MobileActionButton", () => {
|
|
|
369
380
|
buildActionContext({ mobileButtonAssets: undefined })
|
|
370
381
|
);
|
|
371
382
|
|
|
372
|
-
const { queryByTestId } = renderNode(nodeWithFlavour1);
|
|
383
|
+
const { queryByTestId } = renderNode({ node: nodeWithFlavour1 });
|
|
373
384
|
|
|
374
385
|
expect(queryByTestId("mobile-action-button-asset")).toBeNull();
|
|
375
386
|
});
|
|
@@ -385,7 +396,7 @@ describe("MobileActionButton", () => {
|
|
|
385
396
|
})
|
|
386
397
|
);
|
|
387
398
|
|
|
388
|
-
const { getByTestId } = renderNode(nodeWithFlavour1);
|
|
399
|
+
const { getByTestId } = renderNode({ node: nodeWithFlavour1 });
|
|
389
400
|
|
|
390
401
|
expect(getByTestId("mobile-action-button-asset")).toBeTruthy();
|
|
391
402
|
});
|
package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts
CHANGED
|
@@ -241,10 +241,21 @@ describe("MobileActionButtons", () => {
|
|
|
241
241
|
expect(overImageResult?.additionalProps?.contentStyle).toMatchObject({
|
|
242
242
|
flexDirection: "column",
|
|
243
243
|
alignItems: "center",
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
paddingTop: 5,
|
|
245
|
+
paddingRight: 6,
|
|
246
|
+
paddingBottom: 7,
|
|
247
|
+
paddingLeft: 8,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
expect(overImageResult?.style).toMatchObject({
|
|
251
|
+
alignItems: "flex-end",
|
|
252
|
+
bottom: 0,
|
|
253
|
+
justifyContent: "flex-start",
|
|
254
|
+
left: 0,
|
|
255
|
+
position: "absolute",
|
|
256
|
+
right: 0,
|
|
257
|
+
top: 0,
|
|
258
|
+
zIndex: 10,
|
|
248
259
|
});
|
|
249
260
|
|
|
250
261
|
expect(
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "./utils";
|
|
7
7
|
import { Button } from "./Button";
|
|
8
8
|
import { buildActionButtonsModel } from "../../ActionButtonsCore/model";
|
|
9
|
+
import { ViewStyle } from "react-native";
|
|
9
10
|
|
|
10
11
|
const CONTAINER_PREFIX = "mobile_buttons_container";
|
|
11
12
|
const BUTTON_PREFIX = "mobile_button";
|
|
@@ -42,9 +43,24 @@ export const MobileActionButtons = ({
|
|
|
42
43
|
return null;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
const {
|
|
47
|
+
container: { stacking, verticalGutter, horizontalGutter },
|
|
48
|
+
} = model;
|
|
49
|
+
|
|
50
|
+
const isVertical = stacking === "vertical";
|
|
51
|
+
const isOverImage = position === "over_image";
|
|
52
|
+
const gutter = isVertical ? verticalGutter : horizontalGutter;
|
|
53
|
+
|
|
54
|
+
const containerPaddings = {
|
|
55
|
+
paddingTop: model.container.margins.top,
|
|
56
|
+
paddingRight: model.container.margins.right,
|
|
57
|
+
paddingBottom: model.container.margins.bottom,
|
|
58
|
+
paddingLeft: model.container.margins.left,
|
|
59
|
+
};
|
|
60
|
+
|
|
45
61
|
const style = {
|
|
46
62
|
alignItems: "center",
|
|
47
|
-
...(
|
|
63
|
+
...(isOverImage
|
|
48
64
|
? {
|
|
49
65
|
position: "absolute",
|
|
50
66
|
zIndex: 10,
|
|
@@ -60,28 +76,18 @@ export const MobileActionButtons = ({
|
|
|
60
76
|
};
|
|
61
77
|
|
|
62
78
|
const contentStyle = {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
...containerPaddings,
|
|
80
|
+
flexDirection: isVertical ? "column" : "row",
|
|
81
|
+
width: isVertical ? "100%" : undefined,
|
|
82
|
+
alignSelf: !isOverImage ? model.container.horizontalAlign : undefined,
|
|
66
83
|
alignItems: model.container.horizontalAlign,
|
|
67
|
-
marginTop: model.container.margins.top,
|
|
68
|
-
marginRight: model.container.margins.right,
|
|
69
|
-
marginBottom: model.container.margins.bottom,
|
|
70
|
-
marginLeft: model.container.margins.left,
|
|
71
84
|
};
|
|
72
85
|
|
|
73
86
|
const elements = compact(
|
|
74
87
|
model.buttons.map(({ renderIndex, specificPrefix, stylePrefix }) => {
|
|
75
88
|
const isNotLast = renderIndex < model.buttons.length - 1;
|
|
76
89
|
|
|
77
|
-
const {
|
|
78
|
-
container: { stacking, verticalGutter, horizontalGutter },
|
|
79
|
-
} = model;
|
|
80
|
-
|
|
81
|
-
const isVertical = stacking === "vertical";
|
|
82
|
-
const gutter = isVertical ? verticalGutter : horizontalGutter;
|
|
83
|
-
|
|
84
|
-
const spacingStyle = {
|
|
90
|
+
const spacingStyle: ViewStyle = {
|
|
85
91
|
[isVertical ? "marginBottom" : "marginRight"]: isNotLast ? gutter : 0,
|
|
86
92
|
};
|
|
87
93
|
|
|
@@ -91,6 +97,7 @@ export const MobileActionButtons = ({
|
|
|
91
97
|
stylePrefix,
|
|
92
98
|
specificPrefix,
|
|
93
99
|
spacingStyle,
|
|
100
|
+
isVertical,
|
|
94
101
|
});
|
|
95
102
|
|
|
96
103
|
if (!button) return null;
|
|
@@ -5,14 +5,19 @@ import {
|
|
|
5
5
|
} from "..";
|
|
6
6
|
|
|
7
7
|
describe("mobile action insertion helpers", () => {
|
|
8
|
-
const
|
|
8
|
+
const slots = [
|
|
9
|
+
{ name: "text_label_1", element: { type: "View", id: "text_label_1" } },
|
|
10
|
+
{ name: "text_label_2", element: { type: "View", id: "text_label_2" } },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const labels = slots.map((slot) => slot.element);
|
|
9
14
|
const buttons = { type: "View", name: "buttons" };
|
|
10
15
|
|
|
11
16
|
it("inserts label buttons below target label", () => {
|
|
12
17
|
const result = insertButtonsBetweenLabels(
|
|
13
18
|
{ mobile_buttons_container_position: "below_text_label_1" },
|
|
14
19
|
buttons,
|
|
15
|
-
|
|
20
|
+
slots
|
|
16
21
|
);
|
|
17
22
|
|
|
18
23
|
expect(result).toEqual([labels[0], buttons, labels[1]]);
|
|
@@ -22,7 +27,7 @@ describe("mobile action insertion helpers", () => {
|
|
|
22
27
|
const result = insertButtonsBetweenLabels(
|
|
23
28
|
{ mobile_buttons_container_position: "unknown" },
|
|
24
29
|
buttons,
|
|
25
|
-
|
|
30
|
+
slots
|
|
26
31
|
);
|
|
27
32
|
|
|
28
33
|
expect(result).toEqual([labels[0], labels[1]]);
|
|
@@ -8,7 +8,7 @@ import { Platform } from "react-native";
|
|
|
8
8
|
export const insertButtonsBetweenLabels = (
|
|
9
9
|
configuration: Record<string, unknown>,
|
|
10
10
|
buttons,
|
|
11
|
-
|
|
11
|
+
slots = [] // { name, element } per canonical text label slot
|
|
12
12
|
) =>
|
|
13
13
|
insertBetweenLabels(
|
|
14
14
|
{
|
|
@@ -19,7 +19,7 @@ export const insertButtonsBetweenLabels = (
|
|
|
19
19
|
appendWhenMissing: false,
|
|
20
20
|
},
|
|
21
21
|
buttons,
|
|
22
|
-
|
|
22
|
+
slots
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
export const insertButtonsBetweenLabelContainers = (
|
|
@@ -3,18 +3,20 @@ import { insertButtonsBetweenLabels } from "..";
|
|
|
3
3
|
describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
4
4
|
const buttons = "buttons";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
{ name: "label_1" },
|
|
8
|
-
{ name: "label_2" },
|
|
9
|
-
{ name: "label_3" },
|
|
6
|
+
const slots = [
|
|
7
|
+
{ name: "label_1", element: { id: "label_1" } },
|
|
8
|
+
{ name: "label_2", element: { id: "label_2" } },
|
|
9
|
+
{ name: "label_3", element: { id: "label_3" } },
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
+
const labels = slots.map((slot) => slot.element);
|
|
13
|
+
|
|
12
14
|
it("put buttons on top", () => {
|
|
13
15
|
const configuration = {
|
|
14
16
|
tv_buttons_container_position: "on_top",
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
19
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
18
20
|
|
|
19
21
|
expect(result).toEqual([buttons, ...labels]);
|
|
20
22
|
});
|
|
@@ -24,7 +26,7 @@ describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
|
24
26
|
tv_buttons_container_position: "unknown_position",
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
29
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
28
30
|
|
|
29
31
|
expect(result).toEqual([...labels, buttons]);
|
|
30
32
|
});
|
|
@@ -34,7 +36,7 @@ describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
|
34
36
|
tv_buttons_container_position: "label_1",
|
|
35
37
|
};
|
|
36
38
|
|
|
37
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
39
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
38
40
|
|
|
39
41
|
expect(result).toEqual([labels[0], buttons, labels[1], labels[2]]);
|
|
40
42
|
});
|
|
@@ -44,7 +46,7 @@ describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
|
44
46
|
tv_buttons_container_position: "label_2",
|
|
45
47
|
};
|
|
46
48
|
|
|
47
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
49
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
48
50
|
|
|
49
51
|
expect(result).toEqual([labels[0], labels[1], buttons, labels[2]]);
|
|
50
52
|
});
|
|
@@ -54,22 +56,52 @@ describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
|
54
56
|
tv_buttons_container_position: "label_3",
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
59
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
58
60
|
|
|
59
61
|
expect(result).toEqual([labels[0], labels[1], labels[2], buttons]);
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
it("put
|
|
64
|
+
it("put above label_2", () => {
|
|
65
|
+
const configuration = {
|
|
66
|
+
tv_buttons_container_position: "above_label_2",
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
70
|
+
|
|
71
|
+
expect(result).toEqual([labels[0], buttons, labels[1], labels[2]]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("keeps the slot when its label is empty (null element)", () => {
|
|
75
|
+
const slotsWithEmpty = [
|
|
76
|
+
{ name: "label_1", element: { id: "label_1" } },
|
|
77
|
+
{ name: "label_2", element: null },
|
|
78
|
+
{ name: "label_3", element: { id: "label_3" } },
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const configuration = {
|
|
82
|
+
tv_buttons_container_position: "above_label_2",
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const result = insertButtonsBetweenLabels(
|
|
86
|
+
configuration,
|
|
87
|
+
buttons,
|
|
88
|
+
slotsWithEmpty
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
expect(result).toEqual([{ id: "label_1" }, buttons, { id: "label_3" }]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("appends buttons when the target is unknown", () => {
|
|
63
95
|
const configuration = {
|
|
64
96
|
tv_buttons_container_position: "label_X",
|
|
65
97
|
};
|
|
66
98
|
|
|
67
|
-
const result = insertButtonsBetweenLabels(configuration, buttons,
|
|
99
|
+
const result = insertButtonsBetweenLabels(configuration, buttons, slots);
|
|
68
100
|
|
|
69
101
|
expect(result).toEqual([labels[0], labels[1], labels[2], buttons]);
|
|
70
102
|
});
|
|
71
103
|
|
|
72
|
-
it("
|
|
104
|
+
it("appends buttons when there are no slots", () => {
|
|
73
105
|
const configuration = {
|
|
74
106
|
tv_buttons_container_position: "label_X",
|
|
75
107
|
};
|
|
@@ -88,7 +120,7 @@ describe("insertButtonsBetweenLabels - depthlevel 1", () => {
|
|
|
88
120
|
tv_buttons_container_position: "label_X",
|
|
89
121
|
};
|
|
90
122
|
|
|
91
|
-
const result = insertButtonsBetweenLabels(configuration, null,
|
|
123
|
+
const result = insertButtonsBetweenLabels(configuration, null, slots);
|
|
92
124
|
|
|
93
125
|
expect(result).toEqual(labels);
|
|
94
126
|
});
|
|
@@ -34,7 +34,7 @@ export const memoizedGetPluginIdentifier = memoizee(getPluginIdentifier);
|
|
|
34
34
|
export const insertButtonsBetweenLabels = (
|
|
35
35
|
configuration: Record<string, unknown>,
|
|
36
36
|
buttons,
|
|
37
|
-
|
|
37
|
+
slots = [] // { name, element } per canonical text label slot
|
|
38
38
|
) =>
|
|
39
39
|
insertBetweenLabels(
|
|
40
40
|
{
|
|
@@ -45,7 +45,7 @@ export const insertButtonsBetweenLabels = (
|
|
|
45
45
|
appendWhenMissing: true,
|
|
46
46
|
},
|
|
47
47
|
buttons,
|
|
48
|
-
|
|
48
|
+
slots
|
|
49
49
|
);
|
|
50
50
|
|
|
51
51
|
export const insertButtonsBetweenLabelContainers = (
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import { isFunction } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
3
|
+
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
3
4
|
|
|
4
5
|
import { functionForName } from "./MappingFunctions";
|
|
5
6
|
import { resolveColor } from "./utils";
|
|
@@ -52,7 +53,8 @@ export function configInflater(
|
|
|
52
53
|
additionalProps?: Record<string, any>;
|
|
53
54
|
data?: Array<{ propName: string; func: Function; args: any[] }>;
|
|
54
55
|
elements?: any[];
|
|
55
|
-
}
|
|
56
|
+
},
|
|
57
|
+
allowDynamicColorsOutsideExtensions: boolean
|
|
56
58
|
) {
|
|
57
59
|
const props = data.reduce(
|
|
58
60
|
(acc, curr) => {
|
|
@@ -68,13 +70,13 @@ export function configInflater(
|
|
|
68
70
|
|
|
69
71
|
if (Array.isArray(elements)) {
|
|
70
72
|
adjustedElements = elements.map((element) =>
|
|
71
|
-
configInflater(entry, element as any)
|
|
73
|
+
configInflater(entry, element as any, allowDynamicColorsOutsideExtensions)
|
|
72
74
|
);
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
return {
|
|
76
78
|
type,
|
|
77
|
-
style: resolveColor(entry, style),
|
|
79
|
+
style: resolveColor(entry, style, allowDynamicColorsOutsideExtensions),
|
|
78
80
|
props,
|
|
79
81
|
elements: adjustedElements,
|
|
80
82
|
};
|
|
@@ -98,9 +100,17 @@ function resolveElementsNode(entry, state, elements) {
|
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
export function defaultDataAdapter(elements) {
|
|
101
|
-
return function elementsBuilder({
|
|
103
|
+
return function elementsBuilder({
|
|
104
|
+
entry,
|
|
105
|
+
state = "default",
|
|
106
|
+
allowDynamicColorsOutsideExtensions,
|
|
107
|
+
}) {
|
|
102
108
|
return resolveElementsNode(entry, state, elements).map((element) =>
|
|
103
|
-
configInflater(
|
|
109
|
+
configInflater(
|
|
110
|
+
entry,
|
|
111
|
+
element,
|
|
112
|
+
toBooleanWithDefaultFalse(allowDynamicColorsOutsideExtensions)
|
|
113
|
+
)
|
|
104
114
|
);
|
|
105
115
|
};
|
|
106
116
|
}
|
|
@@ -2,7 +2,10 @@ import * as R from "ramda";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { v4 as uuid } from "uuid";
|
|
4
4
|
|
|
5
|
+
import { isHorizontalList } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
6
|
+
import { isVideoPreviewEnabled } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/utils";
|
|
5
7
|
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
8
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
6
9
|
import { useScreenState } from "@applicaster/zapp-react-native-utils/screenState";
|
|
7
10
|
import { defaultComponents } from "./DefaultComponents";
|
|
8
11
|
import { defaultDataAdapter } from "./dataAdapter";
|
|
@@ -34,8 +37,8 @@ type MasterCellBuilderOptions = {
|
|
|
34
37
|
containerStyle: any;
|
|
35
38
|
cellOptions?: {
|
|
36
39
|
isRTL?: boolean;
|
|
37
|
-
generateId?: () => string;
|
|
38
40
|
skipButtons?: boolean;
|
|
41
|
+
component?: ZappComponent;
|
|
39
42
|
};
|
|
40
43
|
};
|
|
41
44
|
|
|
@@ -46,7 +49,7 @@ export function masterCellBuilder({
|
|
|
46
49
|
containerStyle = defaultContainerStyle,
|
|
47
50
|
cellOptions = {},
|
|
48
51
|
}: MasterCellBuilderOptions) {
|
|
49
|
-
const {
|
|
52
|
+
const { skipButtons = false, component } = cellOptions;
|
|
50
53
|
|
|
51
54
|
const componentsMap = R.merge(defaultComponents, components);
|
|
52
55
|
const { View } = componentsMap;
|
|
@@ -65,6 +68,7 @@ export function masterCellBuilder({
|
|
|
65
68
|
*/
|
|
66
69
|
function MasterCell({ item, state, ...otherProps }: Props) {
|
|
67
70
|
const { screenData } = useRoute();
|
|
71
|
+
const theme = useTheme();
|
|
68
72
|
|
|
69
73
|
const screenId =
|
|
70
74
|
screenData && "targetScreen" in screenData
|
|
@@ -85,14 +89,35 @@ export function masterCellBuilder({
|
|
|
85
89
|
elementsBuilder({
|
|
86
90
|
entry: item,
|
|
87
91
|
state: getEntryState(state, entryIsSelected),
|
|
92
|
+
allowDynamicColorsOutsideExtensions:
|
|
93
|
+
theme?.allow_dynamic_colors_outside_extensions,
|
|
88
94
|
}),
|
|
89
|
-
[
|
|
95
|
+
[
|
|
96
|
+
state,
|
|
97
|
+
item,
|
|
98
|
+
entryIsSelected,
|
|
99
|
+
theme?.allow_dynamic_colors_outside_extensions,
|
|
100
|
+
] // Assuming that item won't mutate
|
|
90
101
|
);
|
|
91
102
|
|
|
92
103
|
const wrapperRef = React.useRef(null);
|
|
93
104
|
|
|
94
|
-
const cellUUID = React.useMemo<string>(
|
|
95
|
-
|
|
105
|
+
const cellUUID = React.useMemo<string>(() => {
|
|
106
|
+
const isLiveImage = isVideoPreviewEnabled({
|
|
107
|
+
enable_video_preview: component?.rules?.enable_video_preview,
|
|
108
|
+
player_screen_id: component?.rules?.player_screen_id,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const isHL = isHorizontalList(component);
|
|
112
|
+
|
|
113
|
+
return isHL && isLiveImage
|
|
114
|
+
? `${component?.id}-${component?.styles?.cell_plugin_configuration_id}`
|
|
115
|
+
: uuid();
|
|
116
|
+
}, [
|
|
117
|
+
component?.id,
|
|
118
|
+
component?.styles?.cell_plugin_configuration_id,
|
|
119
|
+
component?.rules?.enable_video_preview,
|
|
120
|
+
component?.rules?.player_screen_id,
|
|
96
121
|
screenId,
|
|
97
122
|
item?.id,
|
|
98
123
|
]);
|