@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4757075613 → 12.0.0-alpha.4796013211
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 +3 -3
- package/Components/Cell/Cell.tsx +30 -9
- package/Components/Cell/CellWithFocusable.tsx +23 -9
- package/Components/Cell/TvOSCellComponent.tsx +3 -7
- package/Components/Focusable/Focusable.tsx +6 -1
- package/Components/FocusableGroup/index.tsx +11 -2
- package/Components/FreezeWithCallback/Freeze.tsx +31 -0
- package/Components/FreezeWithCallback/LICENSE +21 -0
- package/Components/FreezeWithCallback/Suspender.tsx +17 -0
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +170 -0
- package/Components/FreezeWithCallback/index.tsx +3 -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/ScreenContainer.tsx +79 -5
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
- package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
- package/Components/Layout/TV/index.tsx +14 -67
- package/Components/Layout/TV/index.web.tsx +33 -0
- package/Components/Layout/index.tsx +15 -11
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +86 -116
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +71 -0
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +34 -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/index.ts +2 -0
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
- package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +7 -1
- package/Components/MasterCell/dataAdapter.ts +21 -7
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/index.tsx +5 -3
- package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
- package/Components/MasterCell/utils/index.ts +33 -35
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/Navigator/StackNavigator.tsx +57 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +20 -3
- package/Components/PlayerImageBackground/index.tsx +34 -8
- 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/River/__tests__/componentsMap.test.js +6 -0
- package/Components/RouteManager/index.tsx +2 -2
- package/Components/Screen/TV/hooks/index.ts +1 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
- package/Components/Screen/TV/index.web.tsx +178 -0
- package/Components/Screen/__tests__/Screen.test.tsx +3 -49
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
- package/Components/Screen/index.tsx +62 -72
- package/Components/Screen/navigationHandler.ts +6 -3
- package/Components/Screen/orientationHandler.ts +18 -7
- package/Components/Screen/utils.ts +16 -0
- package/Components/ScreenResolver/index.tsx +9 -12
- package/Components/Transitioner/Scene.tsx +39 -26
- package/Components/Transitioner/Transitioner.tsx +46 -48
- package/Components/Transitioner/__tests__/Scene.test.js +7 -0
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -0
- package/Components/VideoLive/LiveImageManager.ts +28 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +25 -28
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +66 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +376 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +165 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +473 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +182 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +302 -0
- package/Components/VideoModal/PlayerDetails.tsx +3 -3
- package/Components/VideoModal/PlayerWrapper.tsx +77 -47
- package/Components/VideoModal/VideoModal.tsx +23 -40
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +203 -105
- package/Components/VideoModal/hooks/useModalSize.ts +10 -12
- package/Components/VideoModal/utils.ts +8 -5
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -3
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
- package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
- package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
- package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
- package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
- package/Contexts/FocusableGroupContext/index.ts +7 -0
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
- 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.tsx +20 -0
- package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
- package/const.ts +6 -0
- package/events/index.ts +1 -0
- package/index.js +3 -0
- package/package.json +5 -5
- package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
- /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -7,6 +7,10 @@ import type {
|
|
|
7
7
|
ContainerProps,
|
|
8
8
|
ContainerChildren,
|
|
9
9
|
} from "./types";
|
|
10
|
+
import {
|
|
11
|
+
useIsRTL,
|
|
12
|
+
applyRTLStylesIfNeeded,
|
|
13
|
+
} from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
10
14
|
|
|
11
15
|
const HorizontalSeparator = ({ width }: HorizontalSeparatorProps) => (
|
|
12
16
|
<View style={{ width }} />
|
|
@@ -17,6 +21,7 @@ export function ButtonContainerView({
|
|
|
17
21
|
children,
|
|
18
22
|
...otherProps
|
|
19
23
|
}: ContainerProps) {
|
|
24
|
+
const isRTL = useIsRTL();
|
|
20
25
|
const horizontalGutter = R.pathOr(0, ["horizontalGutter"], otherProps);
|
|
21
26
|
|
|
22
27
|
const filteredChildren = useFilterChildren<ContainerChildren>(children);
|
|
@@ -26,10 +31,13 @@ export function ButtonContainerView({
|
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
return (
|
|
29
|
-
<View style={style}>
|
|
34
|
+
<View style={applyRTLStylesIfNeeded(style, isRTL)}>
|
|
30
35
|
{insertBetween(
|
|
31
36
|
(index) => (
|
|
32
|
-
<HorizontalSeparator
|
|
37
|
+
<HorizontalSeparator
|
|
38
|
+
key={`separator_${index}`}
|
|
39
|
+
width={horizontalGutter}
|
|
40
|
+
/>
|
|
33
41
|
),
|
|
34
42
|
filteredChildren
|
|
35
43
|
)}
|
|
@@ -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",
|
|
@@ -5,6 +5,7 @@ import * as R from "ramda";
|
|
|
5
5
|
|
|
6
6
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
7
7
|
import { normalizeProgressValue } from "./utils";
|
|
8
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
8
9
|
|
|
9
10
|
const ACTION_NAME = "continue-watching";
|
|
10
11
|
const DEFAULT_FILL = 0;
|
|
@@ -27,6 +28,7 @@ const getProgressValue = (
|
|
|
27
28
|
|
|
28
29
|
export const useFillInPercent = (entry: ZappEntry): number => {
|
|
29
30
|
const action = useActions(ACTION_NAME);
|
|
31
|
+
const isActive = useIsScreenActive();
|
|
30
32
|
|
|
31
33
|
const [fillInPercent, setFillInPercent] =
|
|
32
34
|
React.useState<number>(DEFAULT_FILL);
|
|
@@ -39,6 +41,10 @@ export const useFillInPercent = (entry: ZappEntry): number => {
|
|
|
39
41
|
}, []);
|
|
40
42
|
|
|
41
43
|
React.useEffect(() => {
|
|
44
|
+
if (!isActive) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
// refresh progress in UI when it was changed in CW
|
|
43
49
|
const unsubscribe = action?.addDataSourceListener?.(() => {
|
|
44
50
|
getProgressValue(action, entry, (progress) => {
|
|
@@ -49,7 +55,7 @@ export const useFillInPercent = (entry: ZappEntry): number => {
|
|
|
49
55
|
return () => {
|
|
50
56
|
unsubscribe?.();
|
|
51
57
|
};
|
|
52
|
-
}, []);
|
|
58
|
+
}, [isActive]);
|
|
53
59
|
|
|
54
60
|
return fillInPercent;
|
|
55
61
|
};
|
|
@@ -37,14 +37,28 @@ function retrieveData(entry, func, args) {
|
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
39
|
export function configInflater(
|
|
40
|
-
entry,
|
|
41
|
-
{
|
|
40
|
+
entry: any,
|
|
41
|
+
{
|
|
42
|
+
type,
|
|
43
|
+
style,
|
|
44
|
+
additionalProps = {},
|
|
45
|
+
data = [],
|
|
46
|
+
elements,
|
|
47
|
+
}: {
|
|
48
|
+
type: any;
|
|
49
|
+
style: any;
|
|
50
|
+
additionalProps?: Record<string, any>;
|
|
51
|
+
data?: Array<{ propName: string; func: Function; args: any[] }>;
|
|
52
|
+
elements?: any[];
|
|
53
|
+
}
|
|
42
54
|
) {
|
|
43
|
-
const props =
|
|
44
|
-
(acc, curr) =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const props = data.reduce(
|
|
56
|
+
(acc, curr) => {
|
|
57
|
+
acc[curr.propName] = retrieveData(entry, curr.func, curr.args);
|
|
58
|
+
|
|
59
|
+
return acc;
|
|
60
|
+
},
|
|
61
|
+
{ ...additionalProps }
|
|
48
62
|
);
|
|
49
63
|
|
|
50
64
|
let adjustedElements;
|
|
@@ -52,6 +52,8 @@ export function masterCellBuilder({
|
|
|
52
52
|
const { View } = componentsMap;
|
|
53
53
|
const elementsBuilder = dataAdapter(cellConfiguration);
|
|
54
54
|
|
|
55
|
+
// This is very expensive operation
|
|
56
|
+
// Keep calls to minimum
|
|
55
57
|
const hasFocusableInside = hasFocusableInsideBuilder(elementsBuilder);
|
|
56
58
|
|
|
57
59
|
/**
|
|
@@ -74,8 +76,8 @@ export function masterCellBuilder({
|
|
|
74
76
|
const selectedState = screen?.selectedEntry;
|
|
75
77
|
|
|
76
78
|
const entryIsSelected = React.useMemo(
|
|
77
|
-
() => selectedState?.id === item?.id,
|
|
78
|
-
[selectedState?.id]
|
|
79
|
+
() => !!(selectedState?.id && selectedState?.id === item?.id),
|
|
80
|
+
[selectedState?.id, item?.id]
|
|
79
81
|
);
|
|
80
82
|
|
|
81
83
|
const elements = React.useMemo(
|
|
@@ -84,7 +86,7 @@ export function masterCellBuilder({
|
|
|
84
86
|
entry: item,
|
|
85
87
|
state: getEntryState(state, entryIsSelected),
|
|
86
88
|
}),
|
|
87
|
-
[state, item, entryIsSelected]
|
|
89
|
+
[state, item?.id, entryIsSelected] // Assuming that item won't mutate
|
|
88
90
|
);
|
|
89
91
|
|
|
90
92
|
const wrapperRef = React.useRef(null);
|
|
@@ -9,4 +9,13 @@ describe("insertBetween", () => {
|
|
|
9
9
|
|
|
10
10
|
expect(result).toEqual([1, "|", 2, "|", 3]);
|
|
11
11
|
});
|
|
12
|
+
|
|
13
|
+
it("insertBetween", () => {
|
|
14
|
+
const separator = (index) => `separator:${index}`;
|
|
15
|
+
const items = [1, 2, 3];
|
|
16
|
+
|
|
17
|
+
const result = insertBetween(separator, items);
|
|
18
|
+
|
|
19
|
+
expect(result).toEqual([1, "separator:0", 2, "separator:1", 3]);
|
|
20
|
+
});
|
|
12
21
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useMemo } from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
+
import validateColor from "validate-color";
|
|
3
4
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
6
|
|
|
@@ -9,6 +10,7 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
|
|
|
9
10
|
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
10
11
|
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
11
12
|
import { getCellState } from "../../Cell/utils";
|
|
13
|
+
import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
12
14
|
|
|
13
15
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
14
16
|
if (R.isNil(element)) {
|
|
@@ -47,44 +49,29 @@ export const hasElementsSpecificViewType = (viewType) => (elements) => {
|
|
|
47
49
|
return R.any(hasElementSpecificViewType(viewType))(elements);
|
|
48
50
|
};
|
|
49
51
|
|
|
50
|
-
const isColorOrEmpty = (value) =>
|
|
51
|
-
value === null ||
|
|
52
|
-
value === undefined ||
|
|
53
|
-
value === "" ||
|
|
54
|
-
value.startsWith("#") ||
|
|
55
|
-
value.startsWith("rgba") ||
|
|
56
|
-
value === "transparent";
|
|
57
|
-
|
|
58
52
|
function resolveColorForProp(entry, style, colorProp) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
const colorFromProp = style[colorProp];
|
|
54
|
+
const nestedEntryValue = R.path(colorFromProp.split("."), entry);
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
nestedEntryValue === undefined &&
|
|
58
|
+
!validateColor(colorFromProp.replace(".00", "")) // https://github.com/dreamyguy/validate-color/issues/44
|
|
59
|
+
) {
|
|
60
|
+
logWarning(colorFromProp, style, entry, nestedEntryValue);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (nestedEntryValue === null || typeof nestedEntryValue !== "object") {
|
|
70
|
-
logWarning(colorValue, style, entry, nestedEntryValue);
|
|
71
|
-
|
|
72
|
-
return style;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
nestedEntryValue = nestedEntryValue[part];
|
|
76
|
-
}
|
|
63
|
+
const colorValue = getColorFromData({
|
|
64
|
+
data: entry,
|
|
65
|
+
valueFromLayout: colorFromProp,
|
|
66
|
+
});
|
|
77
67
|
|
|
78
|
-
if (
|
|
79
|
-
logWarning(
|
|
68
|
+
if (!colorValue) {
|
|
69
|
+
logWarning(colorProp, style, entry, colorValue);
|
|
80
70
|
|
|
81
71
|
return style;
|
|
82
72
|
}
|
|
83
73
|
|
|
84
|
-
|
|
85
|
-
style[colorProp] = nestedEntryValue;
|
|
86
|
-
|
|
87
|
-
return style;
|
|
74
|
+
return { ...style, [colorProp]: colorValue };
|
|
88
75
|
}
|
|
89
76
|
|
|
90
77
|
export function resolveColor(entry, style) {
|
|
@@ -125,13 +112,24 @@ export const useFilterChildren = <
|
|
|
125
112
|
|
|
126
113
|
const filteredChildren = children.filter((child) => {
|
|
127
114
|
const item = child.props.item;
|
|
128
|
-
const
|
|
115
|
+
const actionIdentifier = child.props.pluginIdentifier;
|
|
116
|
+
const action = actions.actions[actionIdentifier];
|
|
117
|
+
|
|
129
118
|
// context value of specific plugin
|
|
130
|
-
|
|
119
|
+
if (action?.module && action.module.context) {
|
|
120
|
+
const currentValue = action.module.context._currentValue;
|
|
131
121
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
122
|
+
return currentValue?.isActionAvailable
|
|
123
|
+
? currentValue.isActionAvailable(item)
|
|
124
|
+
: true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
masterCellLogger.error({
|
|
128
|
+
message: `Action plugin for ${actionIdentifier} could not be found, check the configuration of your action button`,
|
|
129
|
+
data: { item, action: child.props.pluginIdentifier },
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
return false;
|
|
135
133
|
});
|
|
136
134
|
|
|
137
135
|
return filteredChildren;
|
|
@@ -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,57 @@
|
|
|
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
|
+
import { isLast } from "@applicaster/zapp-react-native-utils/arrayUtils";
|
|
12
|
+
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
13
|
+
|
|
14
|
+
type Components = {
|
|
15
|
+
NavBar: React.ComponentType<any>;
|
|
16
|
+
Background: React.ComponentType<any>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
Components: Components;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const StackNavigator = ({ Components }: Props) => {
|
|
24
|
+
const { mainStack } = useNavigation();
|
|
25
|
+
|
|
26
|
+
const renderScreen = ({ route, state }, index) => {
|
|
27
|
+
const pathAttributes = getPathAttributes({ pathname: route });
|
|
28
|
+
|
|
29
|
+
if (isEmpty(pathAttributes)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// HACK: Adding index to route to avoid conflicts in the navigator.
|
|
34
|
+
// Startup hooks are all using PUSH navigation action to navigate, but their routes are always like root routes.
|
|
35
|
+
// This means some hooks can have the same routes, e.g., ["hooks/context-setter", "/hooks/login-plug", "hooks/context-setter"].
|
|
36
|
+
const routeId = `${route}--${index}`;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<FocusableGroup
|
|
40
|
+
id={route}
|
|
41
|
+
preferredFocus={isLast(index, mainStack.length)}
|
|
42
|
+
excludeFromFocusSearching
|
|
43
|
+
key={routeId}
|
|
44
|
+
>
|
|
45
|
+
<ScreenDataContext.Provider value={state}>
|
|
46
|
+
<PathnameContext.Provider value={route}>
|
|
47
|
+
<ScreenContextProvider pathname={route}>
|
|
48
|
+
<Screen route={route} Components={Components} />
|
|
49
|
+
</ScreenContextProvider>
|
|
50
|
+
</PathnameContext.Provider>
|
|
51
|
+
</ScreenDataContext.Provider>
|
|
52
|
+
</FocusableGroup>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return <>{mainStack.map(renderScreen)}</>;
|
|
57
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StackNavigator } from "./StackNavigator";
|
|
@@ -54,6 +54,11 @@ 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 {
|
|
58
|
+
useModalAnimationContext,
|
|
59
|
+
PlayerAnimationStateEnum,
|
|
60
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
61
|
+
|
|
57
62
|
type Props = {
|
|
58
63
|
Player: React.ComponentType<any>;
|
|
59
64
|
PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
|
|
@@ -63,6 +68,7 @@ type Props = {
|
|
|
63
68
|
mode?: VideoModalMode;
|
|
64
69
|
loadPipesData: (url: string, options: {}) => void;
|
|
65
70
|
disableCastAction?: boolean;
|
|
71
|
+
groupId?: string;
|
|
66
72
|
};
|
|
67
73
|
|
|
68
74
|
type ScreenStyles = ZappRiver["styles"] & {
|
|
@@ -118,6 +124,7 @@ const nativeStyles = {
|
|
|
118
124
|
playerScreen: {
|
|
119
125
|
flex: 1,
|
|
120
126
|
backgroundColor: "black",
|
|
127
|
+
overflow: "hidden",
|
|
121
128
|
},
|
|
122
129
|
playerWrapper: {
|
|
123
130
|
flex: 1,
|
|
@@ -195,6 +202,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
195
202
|
style: videoStyle,
|
|
196
203
|
mode = VideoModalMode.MAXIMIZED,
|
|
197
204
|
disableCastAction = false,
|
|
205
|
+
groupId,
|
|
198
206
|
} = props;
|
|
199
207
|
|
|
200
208
|
// Hooks
|
|
@@ -229,6 +237,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
229
237
|
const screenData = useTargetScreenData(item);
|
|
230
238
|
const { setVisible: showNavBar } = useSetNavbarState();
|
|
231
239
|
|
|
240
|
+
const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
|
|
241
|
+
useModalAnimationContext();
|
|
242
|
+
|
|
232
243
|
const playerEvent = (event, ...args) => {
|
|
233
244
|
playerManager.invokeHandler(event, ...args);
|
|
234
245
|
};
|
|
@@ -241,8 +252,8 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
241
252
|
return;
|
|
242
253
|
}
|
|
243
254
|
|
|
244
|
-
navigator.goBack();
|
|
245
255
|
showNavBar(true);
|
|
256
|
+
navigator.goBack();
|
|
246
257
|
}, [isModal, navigator.goBack, showNavBar]);
|
|
247
258
|
|
|
248
259
|
const playEntry = (entry) => navigator.replaceTop(entry, { mode });
|
|
@@ -446,7 +457,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
446
457
|
if (disableMiniPlayer) {
|
|
447
458
|
navigator.closeVideoModal();
|
|
448
459
|
} else {
|
|
449
|
-
|
|
460
|
+
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
450
461
|
}
|
|
451
462
|
}
|
|
452
463
|
|
|
@@ -621,6 +632,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
621
632
|
style={styles.focusableGroup}
|
|
622
633
|
preferredFocus
|
|
623
634
|
shouldUsePreferredFocus
|
|
635
|
+
groupId={groupId}
|
|
624
636
|
>
|
|
625
637
|
{/* Video player and components */}
|
|
626
638
|
<View
|
|
@@ -641,7 +653,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
641
653
|
autoplay={true}
|
|
642
654
|
controls={false}
|
|
643
655
|
disableCastAction={disableCastAction}
|
|
644
|
-
docked={
|
|
656
|
+
docked={
|
|
657
|
+
navigator.isVideoModalDocked() &&
|
|
658
|
+
!startComponentsAnimation &&
|
|
659
|
+
!isActiveGesture
|
|
660
|
+
}
|
|
645
661
|
entry={item}
|
|
646
662
|
fullscreen={mode === VideoModalMode.FULLSCREEN}
|
|
647
663
|
inline={inline}
|
|
@@ -659,6 +675,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
659
675
|
setNextVideoPreloadThresholdPercentage={
|
|
660
676
|
setNextVideoPreloadThresholdPercentage
|
|
661
677
|
}
|
|
678
|
+
startComponentsAnimation={startComponentsAnimation}
|
|
662
679
|
>
|
|
663
680
|
{renderApplePlayer(applePlayerProps)}
|
|
664
681
|
</Player>
|
|
@@ -1,38 +1,64 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
import { ImageBackground } from "react-native";
|
|
2
|
+
import { ImageBackground, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
|
+
import {
|
|
6
|
+
AnimationComponent,
|
|
7
|
+
ComponentAnimationType,
|
|
8
|
+
useModalAnimationContext,
|
|
9
|
+
PlayerAnimationStateEnum,
|
|
10
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
5
11
|
|
|
6
12
|
type Props = PropsWithChildren<{
|
|
7
13
|
entry: ZappEntry;
|
|
8
14
|
style?: { [K: string]: any };
|
|
9
15
|
imageStyle?: { [K: string]: any };
|
|
10
16
|
imageKey?: string;
|
|
17
|
+
defaultImageDimensions?: { [K: string]: any };
|
|
11
18
|
}>;
|
|
12
19
|
|
|
20
|
+
const imageSize = { width: "100%", height: "100%" };
|
|
21
|
+
|
|
13
22
|
const PlayerImageBackgroundComponent = ({
|
|
14
23
|
entry,
|
|
15
24
|
children,
|
|
16
25
|
style,
|
|
17
26
|
imageStyle,
|
|
18
27
|
imageKey,
|
|
28
|
+
defaultImageDimensions,
|
|
19
29
|
}: Props) => {
|
|
20
30
|
const source = React.useMemo(
|
|
21
31
|
() => ({ uri: imageSrcFromMediaItem(entry, imageKey) }),
|
|
22
32
|
[imageKey, entry]
|
|
23
33
|
);
|
|
24
34
|
|
|
35
|
+
const { playerAnimationState } = useModalAnimationContext();
|
|
36
|
+
|
|
25
37
|
if (!source) return <>{children}</>;
|
|
26
38
|
|
|
27
39
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
<View
|
|
41
|
+
style={
|
|
42
|
+
playerAnimationState === PlayerAnimationStateEnum.maximaze
|
|
43
|
+
? defaultImageDimensions
|
|
44
|
+
: style
|
|
45
|
+
}
|
|
33
46
|
>
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
<AnimationComponent
|
|
48
|
+
style={style}
|
|
49
|
+
animationType={ComponentAnimationType.player}
|
|
50
|
+
additionalData={defaultImageDimensions}
|
|
51
|
+
>
|
|
52
|
+
<ImageBackground
|
|
53
|
+
resizeMode="cover"
|
|
54
|
+
style={imageSize}
|
|
55
|
+
imageStyle={imageStyle}
|
|
56
|
+
source={source}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</ImageBackground>
|
|
60
|
+
</AnimationComponent>
|
|
61
|
+
</View>
|
|
36
62
|
);
|
|
37
63
|
};
|
|
38
64
|
|