@applicaster/zapp-react-native-ui-components 15.1.0-rc.8 → 16.0.0-alpha.1833861900
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.tsx +42 -0
- package/Components/BackgroundImage/BackgroundImage.tv.android.tsx +28 -0
- package/Components/BackgroundImage/BackgroundImage.tv.ios.tsx +24 -0
- package/Components/BackgroundImage/index.ts +1 -0
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/FocusableWrapper.tsx +3 -0
- package/Components/Cell/TvOSCellComponent.tsx +6 -3
- package/Components/CellRendererResolver/index.ts +1 -1
- package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +41 -8
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
- package/Components/Layout/TV/NavBarContainer.tsx +1 -10
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
- package/Components/Layout/TV/index.tsx +5 -7
- package/Components/Layout/TV/index.web.tsx +5 -7
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +187 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +170 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -10
- package/Components/MasterCell/DefaultComponents/Button.tsx +0 -15
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tv.android.tsx +58 -0
- package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
- package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
- package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +34 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +11 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
- package/Components/MasterCell/DefaultComponents/index.ts +9 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +135 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +22 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +125 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +16 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +37 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +393 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +343 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +122 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +118 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
- package/Components/MasterCell/MappingFunctions/index.js +3 -2
- package/Components/MasterCell/README.md +4 -0
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
- package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
- package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
- package/Components/MasterCell/dataAdapter.ts +4 -1
- package/Components/MasterCell/elementMapper.tsx +52 -7
- package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
- package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
- package/Components/MasterCell/utils/index.ts +85 -15
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +15 -14
- package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +284 -0
- package/Components/River/ComponentsMap/ComponentsMap.tsx +6 -19
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/RefreshControl.tsx +19 -88
- package/Components/River/River.tsx +9 -82
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -0
- package/Components/River/__tests__/componentsMap.test.js +38 -0
- package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
- package/Components/River/hooks/index.ts +1 -0
- package/Components/River/hooks/usePullToRefresh.ts +51 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +65 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +2 -3
- package/Components/Screen/index.tsx +2 -3
- package/Components/Screen/orientationHandler.ts +3 -3
- package/Components/ScreenResolver/index.tsx +9 -5
- package/Components/ScreenRevealManager/Overlay.tsx +34 -0
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +9 -20
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
- package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
- package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
- package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
- package/Components/TopCutoffOverlay/index.tsx +55 -0
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/utils.ts +18 -10
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
- package/Components/Viewport/ViewportAware/index.tsx +16 -7
- package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
- package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -6
- package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
- package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
- package/Contexts/ScreenContext/index.tsx +25 -18
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/Helpers/index.js +7 -1
- package/package.json +5 -5
- package/Components/Layout/TV/LayoutBackground.tsx +0 -28
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
- package/Components/River/TV/withTVEventHandler.tsx +0 -36
- package/Helpers/DataSourceHelper/index.js +0 -19
|
@@ -1,32 +1,40 @@
|
|
|
1
1
|
import { mergeRight } from "ramda";
|
|
2
2
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useAppSelector,
|
|
5
|
+
useContentTypes,
|
|
6
|
+
} from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
7
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
5
8
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
|
|
6
9
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
7
10
|
import { create } from "zustand";
|
|
11
|
+
import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
|
+
import { selectPluginConfigurationsByPluginId } from "@applicaster/zapp-react-native-redux";
|
|
13
|
+
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
8
14
|
|
|
9
15
|
export const useConfiguration = () => {
|
|
10
16
|
const {
|
|
11
17
|
videoModalState: { item },
|
|
12
18
|
} = useNavigation();
|
|
13
19
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"pluginConfigurations",
|
|
18
|
-
]);
|
|
20
|
+
const rivers = useRivers();
|
|
21
|
+
const contentTypes = useContentTypes();
|
|
22
|
+
const player = usePlayer();
|
|
19
23
|
|
|
20
24
|
const targetScreenId = contentTypes?.[item?.type?.value]?.screen_id;
|
|
21
25
|
const targetScreenConfiguration = rivers?.[targetScreenId];
|
|
22
26
|
|
|
23
|
-
const
|
|
24
|
-
|
|
27
|
+
const { configuration_json } = useAppSelector((state) =>
|
|
28
|
+
selectPluginConfigurationsByPluginId(state, targetScreenConfiguration?.type)
|
|
29
|
+
);
|
|
25
30
|
|
|
26
|
-
const playerPluginConfig =
|
|
31
|
+
const playerPluginConfig =
|
|
32
|
+
player?.getPluginConfiguration() ??
|
|
33
|
+
playerManager.getInstanceController()?.getPluginConfiguration() ??
|
|
34
|
+
{};
|
|
27
35
|
|
|
28
36
|
const config = mergeRight(playerPluginConfig, {
|
|
29
|
-
...
|
|
37
|
+
...configuration_json,
|
|
30
38
|
...targetScreenConfiguration?.general,
|
|
31
39
|
...targetScreenConfiguration?.styles,
|
|
32
40
|
});
|
|
@@ -32,7 +32,7 @@ function getTestDimensions(testDimensions) {
|
|
|
32
32
|
return (process.env.NODE_ENV === "test" && testDimensions) || null;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function ViewportAwareComponent(props: Props,
|
|
35
|
+
function ViewportAwareComponent(props: Props, forwardedRef) {
|
|
36
36
|
const viewportEvents = useViewportEventsContext();
|
|
37
37
|
|
|
38
38
|
const {
|
|
@@ -47,13 +47,22 @@ function ViewportAwareComponent(props: Props, ref) {
|
|
|
47
47
|
getTestDimensions(testDimensions) || initialDimensions
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
+
const localRef = React.useRef(null);
|
|
51
|
+
|
|
50
52
|
const [viewportChangeEvent, setViewportChangeEvent] = React.useState(null);
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
const assignRef = React.useCallback(
|
|
55
|
+
(_ref) => {
|
|
56
|
+
localRef.current = _ref;
|
|
57
|
+
|
|
58
|
+
if (typeof forwardedRef === "function") {
|
|
59
|
+
forwardedRef(_ref);
|
|
60
|
+
} else if (forwardedRef) {
|
|
61
|
+
forwardedRef.current = _ref;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
[forwardedRef]
|
|
65
|
+
);
|
|
57
66
|
|
|
58
67
|
const checkInViewport = (viewportChangeEvent, layoutEvent) => {
|
|
59
68
|
const inVerticalViewport = Utils.isInViewport(
|
|
@@ -94,7 +103,7 @@ function ViewportAwareComponent(props: Props, ref) {
|
|
|
94
103
|
const onViewportChange = (viewportChangeEvent) => {
|
|
95
104
|
setViewportChangeEvent(viewportChangeEvent);
|
|
96
105
|
|
|
97
|
-
const nodeHandle = findNodeHandle(
|
|
106
|
+
const nodeHandle = findNodeHandle(localRef.current);
|
|
98
107
|
|
|
99
108
|
if (!nodeHandle) {
|
|
100
109
|
return;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { StyleSheet } from "react-native";
|
|
3
|
-
import { SafeAreaView } from "react-native-safe-area-context";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
4
3
|
|
|
5
4
|
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
6
5
|
import CloseButton from "./Buttons/CloseButton";
|
|
@@ -45,15 +44,14 @@ const BarView = ({ screenStyles, barState = defaultState }: Props) => {
|
|
|
45
44
|
);
|
|
46
45
|
|
|
47
46
|
return (
|
|
48
|
-
<
|
|
49
|
-
edges={["top", "left", "right"]}
|
|
47
|
+
<View
|
|
50
48
|
style={[style.view, isRTL ? style.rtlStyle : {}]}
|
|
51
|
-
testID="BarView-
|
|
49
|
+
testID="BarView-Container"
|
|
52
50
|
>
|
|
53
51
|
{backButton}
|
|
54
52
|
<BarTitle title={barState.title} screenStyles={screenStyles} />
|
|
55
53
|
{closeButton}
|
|
56
|
-
</
|
|
54
|
+
</View>
|
|
57
55
|
);
|
|
58
56
|
};
|
|
59
57
|
|
|
@@ -46,7 +46,7 @@ describe("BarView", () => {
|
|
|
46
46
|
<BarView screenStyles={screenStyles} barState={barState} />
|
|
47
47
|
);
|
|
48
48
|
|
|
49
|
-
expect(getByTestId("BarView-
|
|
49
|
+
expect(getByTestId("BarView-Container").props.style).toContainEqual({
|
|
50
50
|
transform: [{ scaleX: -1 }],
|
|
51
51
|
});
|
|
52
52
|
});
|
|
@@ -58,7 +58,7 @@ describe("BarView", () => {
|
|
|
58
58
|
<BarView screenStyles={screenStyles} barState={barState} />
|
|
59
59
|
);
|
|
60
60
|
|
|
61
|
-
expect(getByTestId("BarView-
|
|
61
|
+
expect(getByTestId("BarView-Container").props.style).not.toContainEqual({
|
|
62
62
|
transform: [{ scaleX: -1 }],
|
|
63
63
|
});
|
|
64
64
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DefaultCell } from "./DefaultCell";
|
|
2
2
|
import { GridCell } from "./GridCell";
|
|
3
3
|
import { HeroCell } from "./HeroCell";
|
|
4
|
-
// import { ScreenSelectorLabel } from "./ScreenSelectorLabel";
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Return a view tree ready to be injected with styles etc. Mapping is done
|
|
@@ -15,8 +14,6 @@ export function viewTreeResolver({ component_type }) {
|
|
|
15
14
|
switch (component_type) {
|
|
16
15
|
case "hero":
|
|
17
16
|
return HeroCell;
|
|
18
|
-
// case "screen_picker":
|
|
19
|
-
// return ScreenSelectorLabel;
|
|
20
17
|
case "grid":
|
|
21
18
|
return GridCell;
|
|
22
19
|
case "horizontal_list":
|
|
@@ -16,6 +16,7 @@ import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-co
|
|
|
16
16
|
import { create } from "zustand";
|
|
17
17
|
import { subscribeWithSelector } from "zustand/middleware";
|
|
18
18
|
import { useShallow } from "zustand/react/shallow";
|
|
19
|
+
|
|
19
20
|
import { Animated } from "react-native";
|
|
20
21
|
|
|
21
22
|
interface NavBarStoreState {
|
|
@@ -29,6 +30,8 @@ interface NavBarStoreState {
|
|
|
29
30
|
scrollState: number;
|
|
30
31
|
contentPosition: string;
|
|
31
32
|
scrollYAnimated: Animated.Value;
|
|
33
|
+
hideOnScrollAnimated: Animated.Value;
|
|
34
|
+
hideOnScroll: boolean;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
interface NavBarState {
|
|
@@ -62,24 +65,28 @@ const createStateStore = () =>
|
|
|
62
65
|
);
|
|
63
66
|
|
|
64
67
|
const createStore = () =>
|
|
65
|
-
create
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
68
|
+
create(
|
|
69
|
+
subscribeWithSelector<NavBarStoreState>((set) => ({
|
|
70
|
+
title: "",
|
|
71
|
+
summary: "",
|
|
72
|
+
visible: true,
|
|
73
|
+
height: 0,
|
|
74
|
+
scrollState: 0,
|
|
75
|
+
contentPosition: "",
|
|
76
|
+
scrollYAnimated: new Animated.Value(0),
|
|
77
|
+
hideOnScrollAnimated: new Animated.Value(0),
|
|
78
|
+
hideOnScroll: false,
|
|
79
|
+
setTitle(title) {
|
|
80
|
+
set({ title });
|
|
81
|
+
},
|
|
82
|
+
setSummary(summary) {
|
|
83
|
+
set({ summary });
|
|
84
|
+
},
|
|
85
|
+
setVisible(visible) {
|
|
86
|
+
set({ visible });
|
|
87
|
+
},
|
|
88
|
+
}))
|
|
89
|
+
);
|
|
83
90
|
|
|
84
91
|
const createScreenComponentsStore = () =>
|
|
85
92
|
create(subscribeWithSelector<Record<string, unknown>>((_) => ({})));
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import { getAnalyticsFunctions } from "@applicaster/zapp-react-native-utils/analyticsUtils";
|
|
4
|
-
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
5
4
|
|
|
6
5
|
type ComponentProps = {
|
|
7
6
|
component: {
|
|
@@ -21,11 +20,13 @@ type ComponentProps = {
|
|
|
21
20
|
|
|
22
21
|
function withAnalytics(Component) {
|
|
23
22
|
return function WithAnalytics(props: ComponentProps) {
|
|
24
|
-
const { appData } = usePickFromState(["appData"]);
|
|
25
|
-
|
|
26
23
|
const analyticsFunctions = React.useMemo(
|
|
27
|
-
() =>
|
|
28
|
-
|
|
24
|
+
() =>
|
|
25
|
+
getAnalyticsFunctions({
|
|
26
|
+
component: props.component,
|
|
27
|
+
zappPipesData: props.zappPipesData,
|
|
28
|
+
} as any),
|
|
29
|
+
[props.component, props.zappPipesData]
|
|
29
30
|
);
|
|
30
31
|
|
|
31
32
|
return (
|
|
@@ -88,6 +88,7 @@ exports[`withConfigurationProvider correctly passes all the configuration keys c
|
|
|
88
88
|
tab_cell_padding_right={10}
|
|
89
89
|
tab_cell_padding_top={14}
|
|
90
90
|
tablet_theme={false}
|
|
91
|
+
tabs_screen_background_color="transparent"
|
|
91
92
|
target={false}
|
|
92
93
|
target_screen_switch={false}
|
|
93
94
|
text_label_active_font_color="rgba(239, 239, 239, 0.5)"
|
|
@@ -208,4 +208,5 @@ export const keysMap: Record<string, Function> = {
|
|
|
208
208
|
tab_bar_item_margin_right: castOrDefaultValue(Number, 0),
|
|
209
209
|
tab_bar_item_margin_bottom: castOrDefaultValue(Number, 0),
|
|
210
210
|
tab_bar_item_margin_left: castOrDefaultValue(Number, 0),
|
|
211
|
+
tabs_screen_background_color: castOrDefaultValue(R.identity, "transparent"),
|
|
211
212
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import * as useFeedLoaderModule from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader";
|
|
3
|
-
import * as useFeedRefreshModule from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedRefresh";
|
|
4
3
|
import { favoritesListener } from "@applicaster/zapp-react-native-bridge/Favorites";
|
|
5
4
|
import { UrlFeedResolver } from "../resolvers/UrlFeedResolver";
|
|
6
5
|
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
@@ -14,10 +13,6 @@ jest
|
|
|
14
13
|
|
|
15
14
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader");
|
|
16
15
|
|
|
17
|
-
jest.mock(
|
|
18
|
-
"@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedRefresh"
|
|
19
|
-
);
|
|
20
|
-
|
|
21
16
|
jest.mock("@applicaster/zapp-pipes-v2-client");
|
|
22
17
|
|
|
23
18
|
jest.mock("@applicaster/zapp-react-native-bridge/Favorites", () => ({
|
|
@@ -62,6 +57,9 @@ describe("UrlFeedResolver", () => {
|
|
|
62
57
|
component: { ...componentRequiredKeys } as any,
|
|
63
58
|
children: mockChildren,
|
|
64
59
|
riverId: "test-river",
|
|
60
|
+
screenContext: {
|
|
61
|
+
id: "screenId",
|
|
62
|
+
},
|
|
65
63
|
};
|
|
66
64
|
|
|
67
65
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -82,6 +80,9 @@ describe("UrlFeedResolver", () => {
|
|
|
82
80
|
} as any,
|
|
83
81
|
children: mockChildren,
|
|
84
82
|
riverId: "test-river",
|
|
83
|
+
screenContext: {
|
|
84
|
+
id: "screenId",
|
|
85
|
+
},
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -103,6 +104,9 @@ describe("UrlFeedResolver", () => {
|
|
|
103
104
|
} as any,
|
|
104
105
|
children: mockChildren,
|
|
105
106
|
riverId: "test-river",
|
|
107
|
+
screenContext: {
|
|
108
|
+
id: "screenId",
|
|
109
|
+
},
|
|
106
110
|
};
|
|
107
111
|
|
|
108
112
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -132,6 +136,9 @@ describe("UrlFeedResolver", () => {
|
|
|
132
136
|
} as any,
|
|
133
137
|
children: mockChildren,
|
|
134
138
|
riverId: "test-river",
|
|
139
|
+
screenContext: {
|
|
140
|
+
id: "screenId",
|
|
141
|
+
},
|
|
135
142
|
};
|
|
136
143
|
|
|
137
144
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -155,6 +162,9 @@ describe("UrlFeedResolver", () => {
|
|
|
155
162
|
children: mockChildren,
|
|
156
163
|
riverId: "test-river",
|
|
157
164
|
plugins: [],
|
|
165
|
+
screenContext: {
|
|
166
|
+
id: "screenId",
|
|
167
|
+
},
|
|
158
168
|
};
|
|
159
169
|
|
|
160
170
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -173,6 +183,9 @@ describe("UrlFeedResolver", () => {
|
|
|
173
183
|
component: { ...componentRequiredKeys } as any,
|
|
174
184
|
children: mockChildren,
|
|
175
185
|
riverId: "test-river",
|
|
186
|
+
screenContext: {
|
|
187
|
+
id: "screenId",
|
|
188
|
+
},
|
|
176
189
|
};
|
|
177
190
|
|
|
178
191
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -197,6 +210,9 @@ describe("UrlFeedResolver", () => {
|
|
|
197
210
|
},
|
|
198
211
|
},
|
|
199
212
|
] as any,
|
|
213
|
+
screenContext: {
|
|
214
|
+
id: "screenId",
|
|
215
|
+
},
|
|
200
216
|
};
|
|
201
217
|
|
|
202
218
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -215,6 +231,9 @@ describe("UrlFeedResolver", () => {
|
|
|
215
231
|
} as any,
|
|
216
232
|
children: mockChildren,
|
|
217
233
|
riverId: "test-river",
|
|
234
|
+
screenContext: {
|
|
235
|
+
id: "screenId",
|
|
236
|
+
},
|
|
218
237
|
};
|
|
219
238
|
|
|
220
239
|
(useFeedLoaderModule.useFeedLoader as jest.Mock).mockReturnValue({
|
|
@@ -250,6 +269,9 @@ describe("UrlFeedResolver", () => {
|
|
|
250
269
|
children: mockChildren,
|
|
251
270
|
riverId: "test-river",
|
|
252
271
|
isLast: true,
|
|
272
|
+
screenContext: {
|
|
273
|
+
id: "screenId",
|
|
274
|
+
},
|
|
253
275
|
};
|
|
254
276
|
|
|
255
277
|
renderWithProviders(<UrlFeedResolver {...props1} />);
|
|
@@ -272,6 +294,9 @@ describe("UrlFeedResolver", () => {
|
|
|
272
294
|
children: mockChildren,
|
|
273
295
|
riverId: "test-river",
|
|
274
296
|
isLast: false,
|
|
297
|
+
screenContext: {
|
|
298
|
+
id: "screenId",
|
|
299
|
+
},
|
|
275
300
|
};
|
|
276
301
|
|
|
277
302
|
renderWithProviders(<UrlFeedResolver {...props2} />);
|
|
@@ -294,6 +319,9 @@ describe("UrlFeedResolver", () => {
|
|
|
294
319
|
children: mockChildren,
|
|
295
320
|
riverId: "test-river",
|
|
296
321
|
isLast: false,
|
|
322
|
+
screenContext: {
|
|
323
|
+
id: "screenId",
|
|
324
|
+
},
|
|
297
325
|
};
|
|
298
326
|
|
|
299
327
|
renderWithProviders(<UrlFeedResolver {...props3} />);
|
|
@@ -311,6 +339,9 @@ describe("UrlFeedResolver", () => {
|
|
|
311
339
|
component: { ...componentRequiredKeys } as any,
|
|
312
340
|
children: mockChildren,
|
|
313
341
|
riverId: "test-river",
|
|
342
|
+
screenContext: {
|
|
343
|
+
id: "screenId",
|
|
344
|
+
},
|
|
314
345
|
};
|
|
315
346
|
|
|
316
347
|
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -327,22 +358,6 @@ describe("UrlFeedResolver", () => {
|
|
|
327
358
|
});
|
|
328
359
|
});
|
|
329
360
|
|
|
330
|
-
it("should apply feed refresh hook", () => {
|
|
331
|
-
const props = {
|
|
332
|
-
feedUrl: "https://example.com/feed",
|
|
333
|
-
component: { ...componentRequiredKeys } as any,
|
|
334
|
-
children: mockChildren,
|
|
335
|
-
riverId: "test-river",
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
renderWithProviders(<UrlFeedResolver {...props} />);
|
|
339
|
-
|
|
340
|
-
expect(useFeedRefreshModule.useFeedRefresh).toHaveBeenCalledWith({
|
|
341
|
-
reloadData: mockReloadData,
|
|
342
|
-
component: props.component,
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
361
|
it("should clean up listeners on unmount", () => {
|
|
347
362
|
const props = {
|
|
348
363
|
component: {
|
|
@@ -354,6 +369,9 @@ describe("UrlFeedResolver", () => {
|
|
|
354
369
|
} as any,
|
|
355
370
|
children: mockChildren,
|
|
356
371
|
riverId: "test-river",
|
|
372
|
+
screenContext: {
|
|
373
|
+
id: "screenId",
|
|
374
|
+
},
|
|
357
375
|
};
|
|
358
376
|
|
|
359
377
|
const { unmount } = renderWithProviders(<UrlFeedResolver {...props} />);
|
|
@@ -3,7 +3,7 @@ import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUt
|
|
|
3
3
|
|
|
4
4
|
import * as zappPipesRedux from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
5
5
|
import configureStore from "redux-mock-store";
|
|
6
|
-
import thunk from "redux-thunk";
|
|
6
|
+
import { thunk } from "redux-thunk";
|
|
7
7
|
|
|
8
8
|
import { zappPipesDataConnector } from "../index";
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/// <reference types="@applicaster/zapp-react-native-ui-components" />
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
5
|
-
import {
|
|
5
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
|
|
6
6
|
import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
7
7
|
import { useScreenContext } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
8
8
|
import { ResolverSelector } from "./ResolverSelector";
|
|
@@ -23,7 +23,7 @@ export function zappPipesDataConnector(
|
|
|
23
23
|
) {
|
|
24
24
|
return function WrappedWithZappPipesData(props: Props) {
|
|
25
25
|
const { screenData } = useRoute();
|
|
26
|
-
const
|
|
26
|
+
const plugins = usePlugins();
|
|
27
27
|
const screenContextData = useScreenContext();
|
|
28
28
|
|
|
29
29
|
const {
|
|
@@ -76,7 +76,7 @@ export function StaticFeedResolver({
|
|
|
76
76
|
|
|
77
77
|
const zappPipesDataProps = useMemo(
|
|
78
78
|
() => ({
|
|
79
|
-
zappPipesData: { url, loading, data, error },
|
|
79
|
+
zappPipesData: { url, loading, data, error }, // todo: add applyItemLimit
|
|
80
80
|
reloadData,
|
|
81
81
|
loadNextData: undefined, // Static resolver doesn't support pagination
|
|
82
82
|
}),
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
getInflatedDataSourceUrl,
|
|
10
10
|
getSearchContext,
|
|
11
11
|
useFeedLoader,
|
|
12
|
-
useFeedRefresh,
|
|
13
12
|
useRoute,
|
|
14
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
14
|
+
import { refreshCoordinator } from "@applicaster/zapp-react-native-utils/refreshUtils/RefreshCoordinator";
|
|
15
15
|
|
|
16
16
|
import { ComponentDataSourceContext, ZappPipesDataProps } from "../types";
|
|
17
17
|
import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
|
|
@@ -199,6 +199,8 @@ export function UrlFeedResolver({
|
|
|
199
199
|
const { pathname } = useRoute();
|
|
200
200
|
const screenStateStore = useScreenStateStore();
|
|
201
201
|
|
|
202
|
+
const screenId = (screenContext?.id || "unknown_screen_id") as string;
|
|
203
|
+
|
|
202
204
|
// Setup listeners for data source URL
|
|
203
205
|
useEffect(() => {
|
|
204
206
|
if (!reloadData) {
|
|
@@ -214,10 +216,19 @@ export function UrlFeedResolver({
|
|
|
214
216
|
url: dataSourceUrl,
|
|
215
217
|
pathname,
|
|
216
218
|
screenStateStore,
|
|
219
|
+
component,
|
|
220
|
+
screenId,
|
|
217
221
|
callback: reloadData,
|
|
218
222
|
});
|
|
219
223
|
}
|
|
220
|
-
}, [
|
|
224
|
+
}, [
|
|
225
|
+
dataSourceUrl,
|
|
226
|
+
reloadData,
|
|
227
|
+
pathname,
|
|
228
|
+
screenStateStore,
|
|
229
|
+
component,
|
|
230
|
+
screenId,
|
|
231
|
+
]);
|
|
221
232
|
|
|
222
233
|
// Setup favorites listener
|
|
223
234
|
useEffect(() => {
|
|
@@ -230,11 +241,11 @@ export function UrlFeedResolver({
|
|
|
230
241
|
}
|
|
231
242
|
}, [type, reloadData]);
|
|
232
243
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
});
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
const unregister = refreshCoordinator.register(component, screenId);
|
|
246
|
+
|
|
247
|
+
return () => unregister();
|
|
248
|
+
}, [component, screenId]);
|
|
238
249
|
|
|
239
250
|
const loadNextData = useMemo(
|
|
240
251
|
() => (!isLast && isVerticalListOrGrid(component) ? undefined : loadNext),
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { itemLimitForData } from "..";
|
|
2
|
+
|
|
3
|
+
describe("itemLimitForData (no mocks)", () => {
|
|
4
|
+
test("returns full array when item_limit is undefined (default Infinity)", () => {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const result = itemLimitForData([1, 2, 3], {
|
|
7
|
+
rules: { item_limit: undefined },
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
expect(result).toEqual([1, 2, 3]);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("enforces positive numeric item_limit", () => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const result = itemLimitForData([1, 2, 3, 4], {
|
|
16
|
+
rules: { item_limit: 2 },
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(result).toEqual([1, 2]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("returns empty array when entry is empty", () => {
|
|
23
|
+
const result = itemLimitForData([], {
|
|
24
|
+
rules: { item_limit: 3 },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect(result).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("defaults entry to empty array when it is undefined", () => {
|
|
31
|
+
const result = itemLimitForData(undefined, {
|
|
32
|
+
rules: { item_limit: 5 },
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(result).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("handles missing component", () => {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
const result = itemLimitForData([10, 20, 30], undefined);
|
|
41
|
+
// missing component → item_limit = undefined → fallback to Infinity
|
|
42
|
+
expect(result).toEqual([10, 20, 30]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("handles missing rules object", () => {
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
const result = itemLimitForData([10, 20, 30], {});
|
|
48
|
+
|
|
49
|
+
expect(result).toEqual([10, 20, 30]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("non-positive item_limit should fall back to Infinity", () => {
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
const result = itemLimitForData([1, 2, 3], {
|
|
55
|
+
rules: { item_limit: -10 },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// -10 → invalid → fallback to Infinity → no limit
|
|
59
|
+
expect(result).toEqual([1, 2, 3]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("zero item_limit should fall back to Infinity", () => {
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
const result = itemLimitForData([1, 2, 3], {
|
|
65
|
+
rules: { item_limit: 0 },
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 0 → invalid → fallback to Infinity
|
|
69
|
+
expect(result).toEqual([1, 2, 3]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("NaN item_limit should fall back to Infinity", () => {
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
const result = itemLimitForData([1, 2, 3], {
|
|
75
|
+
rules: { item_limit: NaN },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(result).toEqual([1, 2, 3]);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { toPositiveNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
2
|
+
|
|
3
|
+
export function itemLimitForData(
|
|
4
|
+
entry: ZappEntry[],
|
|
5
|
+
component: {
|
|
6
|
+
rules?: { item_limit?: number | string };
|
|
7
|
+
}
|
|
8
|
+
) {
|
|
9
|
+
if (!component?.rules?.item_limit) {
|
|
10
|
+
return entry;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const itemLimit = toPositiveNumberWithDefault(
|
|
14
|
+
Infinity,
|
|
15
|
+
component?.rules?.item_limit
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return (entry || []).slice(0, itemLimit);
|
|
19
|
+
}
|
package/Helpers/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
+
|
|
1
3
|
export const ASSETS = {
|
|
2
|
-
APP_BACKGROUND_IMAGE:
|
|
4
|
+
APP_BACKGROUND_IMAGE: platformSelect({
|
|
5
|
+
tvos: "app_background_image",
|
|
6
|
+
android_tv: "tv_app_background",
|
|
7
|
+
amazon: "tv_app_background",
|
|
8
|
+
}),
|
|
3
9
|
};
|
|
4
10
|
|
|
5
11
|
export const ANALYTICS_CORE_EVENTS = {
|