@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3804385444 → 12.0.0-alpha.4201443043
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/BaseFocusable/index.tsx +1 -1
- package/Components/Cell/Cell.tsx +5 -5
- package/Components/Cell/CellWithFocusable.tsx +17 -5
- package/Components/FocusableGroup/index.tsx +1 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
- package/Components/Layout/TV/__tests__/index.test.tsx +18 -74
- package/Components/Layout/TV/index.tsx +9 -105
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +111 -52
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/Navigator/StackNavigator.tsx +48 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +12 -6
- package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/TV/River.tsx +0 -23
- package/Components/RouteManager/index.tsx +2 -2
- package/Components/Screen/TV/hooks/index.ts +3 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
- package/Components/Screen/TV/index.web.tsx +179 -0
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
- package/Components/Screen/index.tsx +35 -24
- package/Components/ScreenResolver/index.tsx +3 -1
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +9 -2
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +18 -1
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +11 -4
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +9 -2
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +13 -2
- package/Components/VideoModal/PlayerWrapper.tsx +67 -60
- package/Components/VideoModal/VideoModal.tsx +19 -19
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +94 -25
- package/Contexts/ScreenDataContext/index.ts +3 -0
- package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
- package/events/index.ts +1 -0
- package/package.json +5 -5
- package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -7,33 +7,72 @@ type BorderPosition = "inside" | "outside" | "center";
|
|
|
7
7
|
interface Props {
|
|
8
8
|
style: ImageStyle | ViewStyle;
|
|
9
9
|
borderPosition: BorderPosition;
|
|
10
|
-
borderPaddingTop: number;
|
|
11
|
-
borderPaddingRight: number;
|
|
12
|
-
borderPaddingBottom: number;
|
|
13
|
-
borderPaddingLeft: number;
|
|
14
10
|
children: React.ReactNode;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
|
-
const
|
|
13
|
+
const MARGINS = [
|
|
14
|
+
"marginTop",
|
|
15
|
+
"marginBottom",
|
|
16
|
+
"marginLeft",
|
|
17
|
+
"marginRight",
|
|
18
|
+
] as const;
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
20
|
+
const PADDINGS = [
|
|
21
|
+
"paddingTop",
|
|
22
|
+
"paddingBottom",
|
|
23
|
+
"paddingLeft",
|
|
24
|
+
"paddingRight",
|
|
25
|
+
] as const;
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const isPercentageValue = (value: number | string) => {
|
|
28
|
+
if (typeof value === "string" && value.endsWith("%")) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const calculateContainerSpacing = ({
|
|
36
|
+
spacingKey,
|
|
37
|
+
style,
|
|
38
|
+
additionalSpacing,
|
|
39
|
+
}: {
|
|
40
|
+
spacingKey: typeof MARGINS[number] | typeof PADDINGS[number];
|
|
41
|
+
style: ImageStyle | ViewStyle;
|
|
42
|
+
additionalSpacing: number;
|
|
43
|
+
}) => {
|
|
44
|
+
return {
|
|
45
|
+
[spacingKey]:
|
|
46
|
+
toNumberWithDefaultZero(style[spacingKey]) + additionalSpacing,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getContainerBorderWidth = (
|
|
51
|
+
borderPosition: BorderPosition,
|
|
52
|
+
borderWidth
|
|
53
|
+
) => {
|
|
28
54
|
switch (borderPosition) {
|
|
29
55
|
case "inside":
|
|
30
56
|
return 0;
|
|
31
57
|
case "center":
|
|
32
|
-
return
|
|
58
|
+
return borderWidth / 2;
|
|
33
59
|
case "outside":
|
|
34
|
-
return
|
|
60
|
+
return borderWidth;
|
|
35
61
|
default:
|
|
36
|
-
return
|
|
62
|
+
return borderWidth;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getContainerPadding = (borderPosition: BorderPosition, borderWidth) => {
|
|
67
|
+
switch (borderPosition) {
|
|
68
|
+
case "inside":
|
|
69
|
+
return borderWidth;
|
|
70
|
+
case "center":
|
|
71
|
+
return borderWidth / 2;
|
|
72
|
+
case "outside":
|
|
73
|
+
return 0;
|
|
74
|
+
default:
|
|
75
|
+
return 0;
|
|
37
76
|
}
|
|
38
77
|
};
|
|
39
78
|
|
|
@@ -44,64 +83,84 @@ const InsideBorder = ({
|
|
|
44
83
|
style: ViewStyle;
|
|
45
84
|
borderPosition: BorderPosition;
|
|
46
85
|
}) => {
|
|
47
|
-
if (
|
|
86
|
+
if (borderPosition === "outside") {
|
|
48
87
|
return null;
|
|
49
88
|
}
|
|
50
89
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const borderRadius =
|
|
55
|
-
toNumberWithDefaultZero(style.borderRadius) -
|
|
56
|
-
getBorderPadding(borderPosition, borderWidth);
|
|
90
|
+
const insideBorderWidth =
|
|
91
|
+
borderPosition === "center" ? style.borderWidth / 2 : style.borderWidth;
|
|
57
92
|
|
|
58
93
|
return (
|
|
59
94
|
<View
|
|
60
95
|
style={{
|
|
61
96
|
...StyleSheet.absoluteFillObject,
|
|
62
|
-
|
|
63
|
-
bottom: containerPadding,
|
|
64
|
-
left: containerPadding,
|
|
65
|
-
top: containerPadding,
|
|
66
|
-
borderWidth: borderWidth,
|
|
97
|
+
borderWidth: insideBorderWidth,
|
|
67
98
|
borderColor: style.borderColor,
|
|
68
|
-
borderRadius,
|
|
99
|
+
borderRadius: style.borderRadius,
|
|
69
100
|
}}
|
|
70
101
|
/>
|
|
71
102
|
);
|
|
72
103
|
};
|
|
73
104
|
|
|
74
105
|
export const BorderContainerView = (props: Props) => {
|
|
75
|
-
const {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
style,
|
|
82
|
-
children,
|
|
83
|
-
} = props;
|
|
106
|
+
const { style, children } = props;
|
|
107
|
+
// Return border position prop after re-implementing
|
|
108
|
+
const borderPosition = "outside";
|
|
109
|
+
|
|
110
|
+
const borderWidth = toNumberWithDefaultZero(style.borderWidth);
|
|
111
|
+
const spacing = getContainerPadding(borderPosition, borderWidth);
|
|
84
112
|
|
|
85
113
|
const borderStyleForMissingBorder =
|
|
86
114
|
style?.borderWidth === 0 || !style?.borderColor ? { borderRadius: 0 } : {};
|
|
87
115
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
const updatedMargins = MARGINS.reduce((acc, margin) => {
|
|
117
|
+
const marginValue = calculateContainerSpacing({
|
|
118
|
+
spacingKey: margin,
|
|
119
|
+
style,
|
|
120
|
+
additionalSpacing: spacing,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return { ...acc, ...marginValue };
|
|
124
|
+
}, {});
|
|
125
|
+
|
|
126
|
+
const updatedPaddings = PADDINGS.reduce((acc, padding) => {
|
|
127
|
+
const paddingValue = calculateContainerSpacing({
|
|
128
|
+
spacingKey: padding,
|
|
129
|
+
style,
|
|
130
|
+
additionalSpacing: spacing,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return { ...acc, ...paddingValue };
|
|
134
|
+
}, {});
|
|
135
|
+
|
|
136
|
+
const updatedWidth = style.width
|
|
137
|
+
? isPercentageValue(style.width)
|
|
138
|
+
? style.width
|
|
139
|
+
: toNumberWithDefaultZero(style.width) - spacing * 2
|
|
140
|
+
: undefined;
|
|
141
|
+
|
|
142
|
+
const updatedHeight = style.height
|
|
143
|
+
? isPercentageValue(style.height)
|
|
144
|
+
? style.height
|
|
145
|
+
: toNumberWithDefaultZero(style.height) - spacing * 2
|
|
146
|
+
: undefined;
|
|
147
|
+
|
|
148
|
+
const containerStyle = {
|
|
149
|
+
borderWidth: getContainerBorderWidth(borderPosition, borderWidth),
|
|
150
|
+
padding: spacing,
|
|
151
|
+
...updatedMargins,
|
|
152
|
+
...updatedPaddings,
|
|
153
|
+
width: updatedWidth,
|
|
154
|
+
height: updatedHeight,
|
|
155
|
+
};
|
|
97
156
|
|
|
98
157
|
return (
|
|
99
|
-
<View
|
|
100
|
-
{...props}
|
|
101
|
-
style={[style, styles.container, borderStyleForMissingBorder, padding]}
|
|
102
|
-
>
|
|
158
|
+
<View {...props} style={[style, containerStyle]}>
|
|
103
159
|
{children}
|
|
104
|
-
<InsideBorder
|
|
160
|
+
<InsideBorder
|
|
161
|
+
style={{ ...style, ...borderStyleForMissingBorder }}
|
|
162
|
+
borderPosition={borderPosition}
|
|
163
|
+
/>
|
|
105
164
|
</View>
|
|
106
165
|
);
|
|
107
166
|
};
|
|
@@ -4,6 +4,7 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
|
|
|
4
4
|
|
|
5
5
|
type DynamicBadgeProps = {
|
|
6
6
|
cellUUID?: string;
|
|
7
|
+
uri?: string;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
@@ -12,11 +13,12 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
|
12
13
|
// TODO: Initial value should depends on player state (playing or not)
|
|
13
14
|
const [showImage, setShowImage] = React.useState(true);
|
|
14
15
|
const player = usePlayer(playerId);
|
|
16
|
+
const uri = props?.uri;
|
|
15
17
|
|
|
16
18
|
React.useEffect(() => {
|
|
17
19
|
if (playerId && player) {
|
|
18
20
|
return player.addListener({
|
|
19
|
-
id:
|
|
21
|
+
id: `dynamic-badges-${uri}`,
|
|
20
22
|
listener: {
|
|
21
23
|
onPlayerClose: () => {
|
|
22
24
|
setShowImage(true);
|
|
@@ -35,7 +37,7 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
|
35
37
|
} else {
|
|
36
38
|
setShowImage(true);
|
|
37
39
|
}
|
|
38
|
-
}, [player]);
|
|
40
|
+
}, [player, uri]);
|
|
39
41
|
|
|
40
42
|
if (!showImage) {
|
|
41
43
|
return null;
|
|
@@ -43,14 +43,16 @@ function Image({
|
|
|
43
43
|
[source, error]
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
+
const _source = shouldRenderImg
|
|
47
|
+
? withDimensions(source)
|
|
48
|
+
: defaultPlaceHolderImage;
|
|
49
|
+
|
|
46
50
|
return (
|
|
47
51
|
// @ts-ignore
|
|
48
52
|
<MemoizedImage
|
|
49
53
|
style={style as ImageStyle}
|
|
50
54
|
onError={() => setErrorState(true)}
|
|
51
|
-
source={
|
|
52
|
-
shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
|
|
53
|
-
}
|
|
55
|
+
source={_source?.uri ? _source : undefined}
|
|
54
56
|
{...R.omit(["source"], otherProps)}
|
|
55
57
|
/>
|
|
56
58
|
);
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { isVideoPreviewEnabled } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/utils";
|
|
3
3
|
import { LiveImage } from "../LiveImage";
|
|
4
4
|
import PureImage from "../Image";
|
|
5
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
6
|
|
|
6
7
|
type Props = {
|
|
7
8
|
enable_video_preview: boolean;
|
|
@@ -9,7 +10,10 @@ type Props = {
|
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export const ImageContainer = (props: Props) => {
|
|
12
|
-
const
|
|
13
|
+
const isActive = useIsScreenActive();
|
|
14
|
+
|
|
15
|
+
const Component =
|
|
16
|
+
isVideoPreviewEnabled(props) && isActive ? LiveImage : PureImage;
|
|
13
17
|
|
|
14
18
|
return <Component {...props} />;
|
|
15
19
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import { omit } from "ramda";
|
|
4
|
-
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
5
4
|
import {
|
|
6
5
|
textTransform,
|
|
7
6
|
dateFormat,
|
|
@@ -9,6 +8,9 @@ import {
|
|
|
9
8
|
|
|
10
9
|
import { useTextLabel, withFocusedStyles } from "./hooks";
|
|
11
10
|
import { withScaledLineHeight } from "./utils";
|
|
11
|
+
import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
12
|
+
import { MeasurementPortalContext } from "../../../MeasurmentsPortal";
|
|
13
|
+
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
12
14
|
|
|
13
15
|
type Props = {
|
|
14
16
|
style: any;
|
|
@@ -32,14 +34,24 @@ const _Text = ({
|
|
|
32
34
|
...otherProps
|
|
33
35
|
}: Props) => {
|
|
34
36
|
const _label = useTextLabel({ label, entry });
|
|
37
|
+
const isMeasurement = React.useContext(MeasurementPortalContext);
|
|
35
38
|
|
|
36
39
|
if (isNilOrEmpty(_label)) {
|
|
37
40
|
return null;
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
// set maximum possible height for the text in case of measurement
|
|
44
|
+
const height =
|
|
45
|
+
isMeasurement && otherProps.numberOfLines && style.lineHeight
|
|
46
|
+
? toNumber(otherProps.numberOfLines) * toNumber(style.lineHeight)
|
|
47
|
+
: undefined;
|
|
48
|
+
|
|
40
49
|
return (
|
|
41
50
|
<Text
|
|
42
|
-
style={
|
|
51
|
+
style={[
|
|
52
|
+
withScaledLineHeight(withFocusedStyles({ style, otherProps })),
|
|
53
|
+
{ height },
|
|
54
|
+
]}
|
|
43
55
|
{...withoutLabel(otherProps)}
|
|
44
56
|
>
|
|
45
57
|
{dateTransformEnabled
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
2
|
+
import RN from "react-native";
|
|
3
3
|
import { Provider } from "react-redux";
|
|
4
4
|
import TestRenderer from "react-test-renderer";
|
|
5
|
-
import
|
|
6
|
-
import CustomText from "../Text";
|
|
5
|
+
import configureStoreFn from "redux-mock-store";
|
|
7
6
|
|
|
8
|
-
const
|
|
7
|
+
const mockUseIsRTL = jest.fn(() => true);
|
|
8
|
+
const mockGetIsRTL = jest.fn(() => true);
|
|
9
|
+
const mockUseLocalizedStrings = jest.fn(() => ({}));
|
|
10
|
+
const mockGetUILanguage = jest.fn(() => "he-HE");
|
|
11
|
+
|
|
12
|
+
jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
|
|
13
|
+
useIsRTL: mockUseIsRTL,
|
|
14
|
+
getIsRTL: mockGetIsRTL,
|
|
15
|
+
useLocalizedStrings: mockUseLocalizedStrings,
|
|
16
|
+
getUILanguage: mockGetUILanguage,
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const CustomText = require("../Text").default;
|
|
20
|
+
const mockStore = configureStoreFn();
|
|
9
21
|
|
|
10
22
|
const defaultProps = {
|
|
11
23
|
entry: {},
|
|
@@ -22,7 +34,7 @@ const getRenderedText = (label: string, store: any) => {
|
|
|
22
34
|
</Provider>
|
|
23
35
|
);
|
|
24
36
|
|
|
25
|
-
return testRenderer.root.findByType(Text).props.children;
|
|
37
|
+
return testRenderer.root.findByType(RN.Text).props.children;
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
describe("RTL app: Hebrew text contains english word", () => {
|
|
@@ -34,7 +46,7 @@ describe("RTL app: Hebrew text contains english word", () => {
|
|
|
34
46
|
remoteConfigurations: { localizations: { he: {} } },
|
|
35
47
|
appData: {
|
|
36
48
|
languageCode: "he",
|
|
37
|
-
countryCode: "
|
|
49
|
+
countryCode: "IL",
|
|
38
50
|
},
|
|
39
51
|
});
|
|
40
52
|
|
|
@@ -47,18 +59,22 @@ describe("RTL app: Hebrew text contains english word", () => {
|
|
|
47
59
|
|
|
48
60
|
it("Hebrew text contains not first english word", () => {
|
|
49
61
|
const renderedText = getRenderedText(textWithNotFirstEnglishWord, store);
|
|
50
|
-
|
|
51
62
|
expect(renderedText).toEqual(textWithNotFirstEnglishWord);
|
|
52
63
|
});
|
|
53
64
|
|
|
54
65
|
it("Hebrew text doesn't contain english word", () => {
|
|
55
66
|
const renderedText = getRenderedText(textWithoutEnglishWord, store);
|
|
56
|
-
|
|
57
67
|
expect(renderedText).toEqual(textWithoutEnglishWord);
|
|
58
68
|
});
|
|
59
69
|
});
|
|
60
70
|
|
|
61
71
|
describe("LTR app: English text", () => {
|
|
72
|
+
beforeAll(() => {
|
|
73
|
+
mockUseIsRTL.mockReturnValue(false);
|
|
74
|
+
mockGetIsRTL.mockReturnValue(false);
|
|
75
|
+
mockGetUILanguage.mockReturnValue("en-US");
|
|
76
|
+
});
|
|
77
|
+
|
|
62
78
|
const englishText = "Test sentence";
|
|
63
79
|
|
|
64
80
|
const store = mockStore({
|
|
@@ -71,7 +87,6 @@ describe("LTR app: English text", () => {
|
|
|
71
87
|
|
|
72
88
|
it("English text", () => {
|
|
73
89
|
const renderedText = getRenderedText(englishText, store);
|
|
74
|
-
|
|
75
90
|
expect(renderedText).toEqual(englishText);
|
|
76
91
|
});
|
|
77
92
|
});
|
|
@@ -61,7 +61,10 @@ export function ButtonContainerView({
|
|
|
61
61
|
<View style={applyRTLStylesIfNeeded(style, isRTL)}>
|
|
62
62
|
{insertBetween(
|
|
63
63
|
(index) => (
|
|
64
|
-
<HorizontalSeparator
|
|
64
|
+
<HorizontalSeparator
|
|
65
|
+
key={`separator_${index}`}
|
|
66
|
+
width={horizontalGutter}
|
|
67
|
+
/>
|
|
65
68
|
),
|
|
66
69
|
cloneElementsWithIds(buttonIds, filteredChildren)
|
|
67
70
|
)}
|
|
@@ -29,7 +29,10 @@ export function ButtonContainerView({
|
|
|
29
29
|
<View style={style}>
|
|
30
30
|
{insertBetween(
|
|
31
31
|
(index) => (
|
|
32
|
-
<HorizontalSeparator
|
|
32
|
+
<HorizontalSeparator
|
|
33
|
+
key={`separator_${index}`}
|
|
34
|
+
width={horizontalGutter}
|
|
35
|
+
/>
|
|
33
36
|
),
|
|
34
37
|
filteredChildren
|
|
35
38
|
)}
|
|
@@ -51,9 +51,7 @@ export const CollapsibleTextContainer = ({
|
|
|
51
51
|
func: (data) => {
|
|
52
52
|
return getColorFromData({
|
|
53
53
|
data,
|
|
54
|
-
|
|
55
|
-
key: "background_color",
|
|
56
|
-
defaultColor: additionalStyles.backgroundColor,
|
|
54
|
+
valueFromLayout: additionalStyles.backgroundColor,
|
|
57
55
|
});
|
|
58
56
|
},
|
|
59
57
|
propName: "backgroundColor",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import { MeasurementPortalContext } from "./MeasurementsPortal";
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
6
|
Component: React.ElementType;
|
|
@@ -19,13 +20,16 @@ const _MeasurementsPortal = (
|
|
|
19
20
|
{ Component, onLayout, componentProps, containerStyle }: Props,
|
|
20
21
|
ref
|
|
21
22
|
) => (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
// hack for cell to determine if cell is in measurement mode
|
|
24
|
+
<MeasurementPortalContext.Provider value={{}}>
|
|
25
|
+
<View
|
|
26
|
+
onLayout={onLayout}
|
|
27
|
+
style={[styles.container, containerStyle]}
|
|
28
|
+
ref={ref}
|
|
29
|
+
>
|
|
30
|
+
<Component {...componentProps} />
|
|
31
|
+
</View>
|
|
32
|
+
</MeasurementPortalContext.Provider>
|
|
29
33
|
);
|
|
30
34
|
|
|
31
35
|
export const MeasurementsPortal = React.forwardRef(_MeasurementsPortal);
|
|
@@ -35,7 +35,16 @@ const MeasurementsPortal = ({ Component, onLayout, componentProps }: Props) => {
|
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
type MeasurementPortalContextType = {
|
|
39
|
+
measureComponent?: (
|
|
40
|
+
comp: React.ElementType,
|
|
41
|
+
props: Record<any, any>
|
|
42
|
+
) => Promise<any>;
|
|
43
|
+
measuringInProgress?: boolean;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const MeasurementPortalContext =
|
|
47
|
+
React.createContext<null | MeasurementPortalContextType>(null);
|
|
39
48
|
|
|
40
49
|
const MeasurementsPortalContextProvider = ({ children }) => {
|
|
41
50
|
const Component = React.useRef(View);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { isEmpty } from "ramda";
|
|
3
|
+
|
|
4
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
5
|
+
import { getPathAttributes } from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
6
|
+
import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup";
|
|
7
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
8
|
+
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
9
|
+
|
|
10
|
+
import { Screen } from "../Screen/TV/index.web";
|
|
11
|
+
|
|
12
|
+
type Components = {
|
|
13
|
+
NavBar: React.ComponentType<any>;
|
|
14
|
+
Background: React.ComponentType<any>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type Props = {
|
|
18
|
+
Components: Components;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const StackNavigator = ({ Components }: Props) => {
|
|
22
|
+
const { mainStack, currentRoute } = useNavigation();
|
|
23
|
+
|
|
24
|
+
const renderScreen = ({ route, state }) => {
|
|
25
|
+
const pathAttributes = getPathAttributes({ pathname: route });
|
|
26
|
+
|
|
27
|
+
if (isEmpty(pathAttributes)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<FocusableGroup
|
|
33
|
+
id={route}
|
|
34
|
+
preferredFocus={route === currentRoute}
|
|
35
|
+
excludeFromFocusSearching
|
|
36
|
+
key={route}
|
|
37
|
+
>
|
|
38
|
+
<ScreenDataContext.Provider value={state}>
|
|
39
|
+
<PathnameContext.Provider value={route}>
|
|
40
|
+
<Screen route={route} Components={Components} />
|
|
41
|
+
</PathnameContext.Provider>
|
|
42
|
+
</ScreenDataContext.Provider>
|
|
43
|
+
</FocusableGroup>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return <>{mainStack.map(renderScreen)}</>;
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StackNavigator } from "./StackNavigator";
|
|
@@ -54,7 +54,10 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
|
54
54
|
import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
|
|
55
55
|
import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
|
|
56
56
|
|
|
57
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
useModalAnimationContext,
|
|
59
|
+
PlayerAnimationStateEnum,
|
|
60
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
58
61
|
|
|
59
62
|
type Props = {
|
|
60
63
|
Player: React.ComponentType<any>;
|
|
@@ -65,6 +68,7 @@ type Props = {
|
|
|
65
68
|
mode?: VideoModalMode;
|
|
66
69
|
loadPipesData: (url: string, options: {}) => void;
|
|
67
70
|
disableCastAction?: boolean;
|
|
71
|
+
groupId?: string;
|
|
68
72
|
};
|
|
69
73
|
|
|
70
74
|
type ScreenStyles = ZappRiver["styles"] & {
|
|
@@ -197,6 +201,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
197
201
|
style: videoStyle,
|
|
198
202
|
mode = VideoModalMode.MAXIMIZED,
|
|
199
203
|
disableCastAction = false,
|
|
204
|
+
groupId,
|
|
200
205
|
} = props;
|
|
201
206
|
|
|
202
207
|
// Hooks
|
|
@@ -231,6 +236,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
231
236
|
const screenData = useTargetScreenData(item);
|
|
232
237
|
const { setVisible: showNavBar } = useSetNavbarState();
|
|
233
238
|
|
|
239
|
+
const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
|
|
240
|
+
useModalAnimationContext();
|
|
241
|
+
|
|
234
242
|
const playerEvent = (event, ...args) => {
|
|
235
243
|
playerManager.invokeHandler(event, ...args);
|
|
236
244
|
};
|
|
@@ -243,7 +251,6 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
243
251
|
return;
|
|
244
252
|
}
|
|
245
253
|
|
|
246
|
-
navigator.goBack();
|
|
247
254
|
showNavBar(true);
|
|
248
255
|
}, [isModal, navigator.goBack, showNavBar]);
|
|
249
256
|
|
|
@@ -448,7 +455,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
448
455
|
if (disableMiniPlayer) {
|
|
449
456
|
navigator.closeVideoModal();
|
|
450
457
|
} else {
|
|
451
|
-
|
|
458
|
+
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
452
459
|
}
|
|
453
460
|
}
|
|
454
461
|
|
|
@@ -600,9 +607,6 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
600
607
|
pluginConfiguration,
|
|
601
608
|
};
|
|
602
609
|
|
|
603
|
-
const { isActiveGesture, startComponentsAnimation } =
|
|
604
|
-
useModalAnimationContext();
|
|
605
|
-
|
|
606
610
|
return (
|
|
607
611
|
<PlayerStateContext.Provider value={value}>
|
|
608
612
|
<PlayerContainerContextProvider
|
|
@@ -626,6 +630,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
626
630
|
style={styles.focusableGroup}
|
|
627
631
|
preferredFocus
|
|
628
632
|
shouldUsePreferredFocus
|
|
633
|
+
groupId={groupId}
|
|
629
634
|
>
|
|
630
635
|
{/* Video player and components */}
|
|
631
636
|
<View
|
|
@@ -668,6 +673,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
668
673
|
setNextVideoPreloadThresholdPercentage={
|
|
669
674
|
setNextVideoPreloadThresholdPercentage
|
|
670
675
|
}
|
|
676
|
+
startComponentsAnimation={startComponentsAnimation}
|
|
671
677
|
>
|
|
672
678
|
{renderApplePlayer(applePlayerProps)}
|
|
673
679
|
</Player>
|