@applicaster/zapp-react-native-ui-components 13.0.0-alpha.5385326185 → 13.0.0-alpha.5406200595
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/AudioPlayer/AudioPlayer.tsx +5 -9
- package/Components/AudioPlayer/helpers.tsx +1 -2
- package/Components/Cell/Cell.tsx +3 -13
- package/Components/Cell/CellWithFocusable.tsx +21 -15
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/Cell/styles.ts +17 -0
- package/Components/CellRendererResolver/index.ts +2 -1
- package/Components/ErrorScreen/index.tsx +8 -0
- package/Components/FocusableCell/index.tsx +1 -1
- package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
- package/Components/FocusableGroup/index.tsx +0 -3
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
- package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
- package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
- package/Components/Layout/TV/LayoutBackground.tsx +28 -0
- package/Components/Layout/TV/NavBarContainer.tsx +2 -1
- package/Components/Layout/TV/ScreenContainer.tsx +8 -2
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +2 -1
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +1 -0
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +1 -0
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
- package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
- package/Components/Layout/TV/index.tsx +6 -20
- package/Components/Layout/TV/index.web.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
- package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
- package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
- package/Components/MasterCell/utils/index.ts +8 -134
- package/Components/ModalComponent/BottomSheetModalContent.tsx +49 -41
- package/Components/ModalComponent/Button/Item.tsx +6 -5
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +45 -62
- package/Components/ModalComponent/Header/index.tsx +9 -8
- package/Components/ModalComponent/utils.ts +55 -7
- package/Components/OfflineHandler/utils/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +34 -7
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +3 -0
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +3 -3
- package/Components/River/RiverItem.tsx +2 -1
- package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
- package/Components/Screen/TV/index.web.tsx +5 -6
- package/Components/Screen/__tests__/Screen.test.tsx +22 -14
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
- package/Components/Screen/hooks.ts +3 -6
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
- package/Components/TrackedView/index.tsx +1 -0
- package/Components/Transitioner/AnimationManager.js +15 -15
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +4 -0
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +35 -19
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +3 -3
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +38 -14
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +10 -3
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
- package/Components/VideoModal/ModalAnimation/const.ts +5 -0
- package/Components/VideoModal/ModalAnimation/index.ts +2 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +30 -0
- package/Components/VideoModal/PlayerDetails.tsx +13 -5
- package/Components/VideoModal/PlayerWrapper.tsx +35 -22
- package/Components/VideoModal/VideoModal.tsx +19 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
- package/Components/VideoModal/utils.ts +3 -4
- package/Components/ZappUIComponent/index.tsx +4 -4
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
- package/Contexts/HeaderOffsetContext/index.tsx +4 -6
- package/Contexts/ScreenContext/index.tsx +3 -10
- package/Contexts/ScreenLayoutContext/index.tsx +5 -3
- package/Decorators/RiverResolver/index.tsx +5 -7
- package/Decorators/ZappPipesDataConnector/index.tsx +4 -30
- package/package.json +5 -9
- package/tsconfig.json +2 -3
- package/.babelrc +0 -8
- package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
- package/Components/Cell/CellStyles/Hero/index.js +0 -111
- package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
- package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
- package/Components/Cell/CellStyles/colors.js +0 -40
- package/Components/Cell/CellStyles/index.js +0 -15
- package/Components/Cell/CellWithFocusable.ios.tsx +0 -126
|
@@ -60,10 +60,15 @@ export function ScreenLayoutContextProvider(props: {
|
|
|
60
60
|
initialState
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
+
const resetScreenLayout = React.useCallback(() => {
|
|
64
|
+
setScreenLayout(initialState);
|
|
65
|
+
}, [initialState]);
|
|
66
|
+
|
|
63
67
|
const screenLayoutValue = React.useMemo(
|
|
64
68
|
() => ({
|
|
65
69
|
...screenLayout,
|
|
66
70
|
setScreenLayout,
|
|
71
|
+
resetScreenLayout,
|
|
67
72
|
}),
|
|
68
73
|
[screenLayout]
|
|
69
74
|
);
|
|
@@ -56,11 +56,12 @@ describe("ScreenContainer", () => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const setScreenLayout = () => {};
|
|
59
|
+
const resetScreenLayout = () => {};
|
|
59
60
|
|
|
60
61
|
const wrapper = ({ children }) => (
|
|
61
62
|
<WrappedWithProviders>
|
|
62
63
|
<ScreenLayoutContext.Provider
|
|
63
|
-
value={{ ...screenLayout, setScreenLayout }}
|
|
64
|
+
value={{ ...screenLayout, setScreenLayout, resetScreenLayout }}
|
|
64
65
|
>
|
|
65
66
|
<ScreenContainer NavBar={View}>{children}</ScreenContainer>
|
|
66
67
|
</ScreenLayoutContext.Provider>
|
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Layout TV renders 1`] = `
|
|
4
4
|
<View
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
preferredFocus={true}
|
|
5
|
+
backgroundColor="#000000"
|
|
6
|
+
testID="background-component"
|
|
8
7
|
>
|
|
9
8
|
<View
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
excludeFromFocusSearching={true}
|
|
10
|
+
id="/river/A1234"
|
|
11
|
+
preferredFocus={true}
|
|
12
|
+
>
|
|
13
|
+
<View
|
|
14
|
+
Components={
|
|
15
|
+
{
|
|
16
|
+
"Background": [Function],
|
|
17
|
+
"NavBar": [Function],
|
|
18
|
+
}
|
|
14
19
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
route="/river/A1234"
|
|
21
|
+
/>
|
|
22
|
+
</View>
|
|
18
23
|
</View>
|
|
19
24
|
`;
|
|
@@ -5,6 +5,14 @@ import { render } from "@testing-library/react-native";
|
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
6
|
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
|
|
7
7
|
import configureStore from "redux-mock-store";
|
|
8
|
+
import Layout from "../index.web";
|
|
9
|
+
|
|
10
|
+
// mock useTheme to provide app_background_color
|
|
11
|
+
jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
|
|
12
|
+
useTheme: () => ({
|
|
13
|
+
app_background_color: "#000000",
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
8
16
|
|
|
9
17
|
const withoutChildren = omit(["children"]);
|
|
10
18
|
|
|
@@ -16,8 +24,6 @@ jest.mock("../../../Screen/TV/index.web", () => {
|
|
|
16
24
|
};
|
|
17
25
|
});
|
|
18
26
|
|
|
19
|
-
const Layout = require("../index.web").default;
|
|
20
|
-
|
|
21
27
|
const mockStore = configureStore()({
|
|
22
28
|
appState: { appReady: true },
|
|
23
29
|
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import * as R from "ramda";
|
|
3
2
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
3
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
5
|
-
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
6
4
|
|
|
7
|
-
import { getBackgroundImageUrl } from "../utils";
|
|
8
5
|
import { LayoutContainer } from "./LayoutContainer";
|
|
9
6
|
import { ScreenContainer } from "./ScreenContainer";
|
|
10
7
|
|
|
@@ -12,6 +9,7 @@ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
|
|
|
12
9
|
import { PathnameContext } from "../../../Contexts/PathnameContext";
|
|
13
10
|
import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
|
|
14
11
|
import { ScreenContextProvider } from "../../../Contexts/ScreenContext";
|
|
12
|
+
import { LayoutBackground } from "./LayoutBackground";
|
|
15
13
|
|
|
16
14
|
type Components = {
|
|
17
15
|
NavBar: React.ComponentType<any>;
|
|
@@ -19,7 +17,6 @@ type Components = {
|
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
type ComponentsExtraProps = {
|
|
22
|
-
Background?: Record<string, any>;
|
|
23
20
|
NavBar?: Record<string, any>;
|
|
24
21
|
};
|
|
25
22
|
|
|
@@ -31,17 +28,10 @@ type Props = {
|
|
|
31
28
|
|
|
32
29
|
const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
33
30
|
const navigator = useNavigation();
|
|
34
|
-
const theme = useTheme();
|
|
35
31
|
|
|
36
|
-
const { appState: { appReady = false } = {}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const backgroundColor = React.useMemo(() => theme.app_background_color, []);
|
|
40
|
-
|
|
41
|
-
const backgroundImageUrl = React.useMemo(
|
|
42
|
-
() => getBackgroundImageUrl(remoteConfigurations),
|
|
43
|
-
[remoteConfigurations]
|
|
44
|
-
);
|
|
32
|
+
const { appState: { appReady = false } = {} } = usePickFromState([
|
|
33
|
+
"appState",
|
|
34
|
+
]);
|
|
45
35
|
|
|
46
36
|
if (!appReady) {
|
|
47
37
|
return null;
|
|
@@ -50,11 +40,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
50
40
|
return (
|
|
51
41
|
<LayoutContainer>
|
|
52
42
|
<ScreenLayoutContextProvider>
|
|
53
|
-
<Components.Background
|
|
54
|
-
backgroundColor={backgroundColor}
|
|
55
|
-
backgroundImageUrl={backgroundImageUrl}
|
|
56
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.Background)}
|
|
57
|
-
>
|
|
43
|
+
<LayoutBackground Background={Components.Background}>
|
|
58
44
|
<ScreenDataContext.Provider value={navigator.data}>
|
|
59
45
|
<PathnameContext.Provider value={navigator.currentRoute}>
|
|
60
46
|
<ScreenContextProvider pathname={navigator.currentRoute}>
|
|
@@ -67,7 +53,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
67
53
|
</ScreenContextProvider>
|
|
68
54
|
</PathnameContext.Provider>
|
|
69
55
|
</ScreenDataContext.Provider>
|
|
70
|
-
</
|
|
56
|
+
</LayoutBackground>
|
|
71
57
|
</ScreenLayoutContextProvider>
|
|
72
58
|
</LayoutContainer>
|
|
73
59
|
);
|
|
@@ -5,6 +5,7 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
5
5
|
|
|
6
6
|
import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
|
|
7
7
|
import { StackNavigator } from "../../Navigator";
|
|
8
|
+
import { LayoutBackground } from "./LayoutBackground";
|
|
8
9
|
|
|
9
10
|
type Components = {
|
|
10
11
|
NavBar: React.ComponentType<any>;
|
|
@@ -25,7 +26,9 @@ const Layout = ({ Components }: Props) => {
|
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
28
|
<ScreenLayoutContextProvider>
|
|
28
|
-
<
|
|
29
|
+
<LayoutBackground Background={Components.Background}>
|
|
30
|
+
<StackNavigator Components={Components} />
|
|
31
|
+
</LayoutBackground>
|
|
29
32
|
</ScreenLayoutContextProvider>
|
|
30
33
|
);
|
|
31
34
|
};
|
|
@@ -4,7 +4,6 @@ import { TouchableOpacity, ViewStyle } from "react-native";
|
|
|
4
4
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
5
|
|
|
6
6
|
import Image from "./Image";
|
|
7
|
-
|
|
8
7
|
type Props = {
|
|
9
8
|
item: ZappEntry | ZappFeed;
|
|
10
9
|
flavour?: "flavour_1" | "flavour_2";
|
|
@@ -69,7 +68,7 @@ export function ActionButton(props: Props) {
|
|
|
69
68
|
if (!((actionDisabled || !actionContext) && actionState !== null)) {
|
|
70
69
|
setActionState(actionContext.initialEntryState(item));
|
|
71
70
|
}
|
|
72
|
-
}, [actionDisabled, item?.id, actionContext, action]);
|
|
71
|
+
}, [actionDisabled, item?.id, actionContext, action, setActionState]);
|
|
73
72
|
|
|
74
73
|
const onPress = useCallback(() => {
|
|
75
74
|
actionContext.invokeAction(item, {
|
|
@@ -85,7 +84,7 @@ export function ActionButton(props: Props) {
|
|
|
85
84
|
setActionState(state);
|
|
86
85
|
});
|
|
87
86
|
}
|
|
88
|
-
}, [item?.id]);
|
|
87
|
+
}, [item?.id, setActionState, actionContext]);
|
|
89
88
|
|
|
90
89
|
if (actionDisabled || !actionContext) return null;
|
|
91
90
|
const AssetComponent = actionState?.asset;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Image as RnImage, ImageStyle } from "react-native";
|
|
3
|
-
import
|
|
3
|
+
import { equals, omit } from "ramda";
|
|
4
4
|
|
|
5
5
|
import { useImageSource } from "./hooks";
|
|
6
6
|
|
|
@@ -17,7 +17,7 @@ type Props = Record<string, any> & {
|
|
|
17
17
|
withDimensions: (source: Source) => Source;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const MemoizedImage = React.memo(RnImage,
|
|
20
|
+
const MemoizedImage = React.memo(RnImage, equals);
|
|
21
21
|
|
|
22
22
|
function Image({
|
|
23
23
|
style,
|
|
@@ -44,11 +44,12 @@ function Image({
|
|
|
44
44
|
|
|
45
45
|
return (
|
|
46
46
|
<MemoizedImage
|
|
47
|
+
key={_source?.uri || "no-image"}
|
|
47
48
|
style={style as ImageStyle}
|
|
48
49
|
onError={React.useCallback(() => setErrorState(true), [])}
|
|
49
50
|
// as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
|
|
50
51
|
source={_source?.uri ? _source : undefined}
|
|
51
|
-
{...
|
|
52
|
+
{...omit(["source"], otherProps)}
|
|
52
53
|
/>
|
|
53
54
|
);
|
|
54
55
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { path } from "ramda";
|
|
3
3
|
|
|
4
4
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
@@ -7,9 +7,13 @@ import { extractAsset } from "./utils";
|
|
|
7
7
|
|
|
8
8
|
type Return = { uri: string } | null;
|
|
9
9
|
|
|
10
|
+
const getSourceContext = path(["source", "context"]);
|
|
11
|
+
const getSourceUri = path(["source", "uri"]);
|
|
12
|
+
const getState = path(["state"]);
|
|
13
|
+
|
|
10
14
|
export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
11
|
-
const uriContext =
|
|
12
|
-
const uriState =
|
|
15
|
+
const uriContext = getSourceContext(otherProps);
|
|
16
|
+
const uriState = getState(otherProps);
|
|
13
17
|
|
|
14
18
|
const action = useActions(uriContext);
|
|
15
19
|
|
|
@@ -34,7 +38,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
|
34
38
|
return { uri };
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const uriFromSource =
|
|
41
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
38
42
|
|
|
39
43
|
if (uriFromSource) {
|
|
40
44
|
return { uri: uriFromSource };
|
|
@@ -56,7 +60,7 @@ const getSource = (uri, showDefault, placeholderImage, otherProps) => {
|
|
|
56
60
|
return { uri };
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
const uriFromSource =
|
|
63
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
60
64
|
|
|
61
65
|
if (uriFromSource) {
|
|
62
66
|
return { uri: uriFromSource };
|
|
@@ -72,8 +76,8 @@ export const useImageSourceWithDefault = ({
|
|
|
72
76
|
placeholderImage,
|
|
73
77
|
otherProps,
|
|
74
78
|
}): Return => {
|
|
75
|
-
const uriContext =
|
|
76
|
-
const uriState =
|
|
79
|
+
const uriContext = getSourceContext(otherProps);
|
|
80
|
+
const uriState = getState(otherProps);
|
|
77
81
|
|
|
78
82
|
const action = useActions(uriContext);
|
|
79
83
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { times } from "@applicaster/zapp-react-native-utils/utils";
|
|
2
2
|
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
3
3
|
|
|
4
4
|
import { Button } from "./Button";
|
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
} from "./utils";
|
|
10
10
|
|
|
11
11
|
import { compact } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
12
|
+
import { PREFIX, BUTTON_PREFIX } from "./const";
|
|
12
13
|
|
|
13
14
|
export {
|
|
14
15
|
insertButtonsBetweenLabels,
|
|
15
16
|
insertButtonsBetweenLabelContainers,
|
|
16
17
|
} from "./utils";
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const buttonId = (index: number) => `${BUTTON_PREFIX}_${index}`;
|
|
19
20
|
|
|
20
21
|
type Props = {
|
|
21
22
|
value: Function;
|
|
@@ -42,7 +43,6 @@ export const TvActionButtons = ({
|
|
|
42
43
|
return null;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
const prefix1Button = `${PREFIX}_button_1`;
|
|
46
46
|
const independentStyles = value(`${PREFIX}_container_independent_styles`);
|
|
47
47
|
|
|
48
48
|
return {
|
|
@@ -73,11 +73,11 @@ export const TvActionButtons = ({
|
|
|
73
73
|
buttonsCount,
|
|
74
74
|
},
|
|
75
75
|
elements: compact(
|
|
76
|
-
|
|
77
|
-
const prefixSpecificButton =
|
|
76
|
+
times((index) => {
|
|
77
|
+
const prefixSpecificButton = buttonId(index + 1);
|
|
78
78
|
|
|
79
79
|
return Button({
|
|
80
|
-
prefix: independentStyles ? prefixSpecificButton :
|
|
80
|
+
prefix: independentStyles ? prefixSpecificButton : buttonId(1),
|
|
81
81
|
value,
|
|
82
82
|
platformValue,
|
|
83
83
|
pluginIdentifier: getPluginIdentifier(configuration, PREFIX, index),
|
|
@@ -34,7 +34,6 @@ export const useFillInPercent = (entry: ZappEntry): number => {
|
|
|
34
34
|
React.useState<number>(DEFAULT_FILL);
|
|
35
35
|
|
|
36
36
|
React.useEffect(() => {
|
|
37
|
-
// setup progress in UI on mount
|
|
38
37
|
getProgressValue(action, entry, (progress) => {
|
|
39
38
|
setFillInPercent(progress);
|
|
40
39
|
});
|
|
@@ -45,17 +44,12 @@ export const useFillInPercent = (entry: ZappEntry): number => {
|
|
|
45
44
|
return;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
const unsubscribe = action?.addDataSourceListener?.(() => {
|
|
47
|
+
return action?.addDataSourceListener?.(() => {
|
|
50
48
|
getProgressValue(action, entry, (progress) => {
|
|
51
49
|
setFillInPercent(progress);
|
|
52
50
|
});
|
|
53
51
|
});
|
|
54
|
-
|
|
55
|
-
return () => {
|
|
56
|
-
unsubscribe?.();
|
|
57
|
-
};
|
|
58
|
-
}, [isActive]);
|
|
52
|
+
}, [isActive, action, entry, setFillInPercent]);
|
|
59
53
|
|
|
60
54
|
return fillInPercent;
|
|
61
55
|
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
2
|
+
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
|
|
3
|
+
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
4
|
+
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
5
|
+
import React, { useEffect } from "react";
|
|
6
|
+
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
7
|
+
import { BehaviorSubject } from "rxjs";
|
|
8
|
+
import { masterCellLogger } from "../logger";
|
|
9
|
+
import get from "lodash/get";
|
|
10
|
+
|
|
11
|
+
const parseContextKey = (key: string): string | null => {
|
|
12
|
+
if (!key?.startsWith("@{ctx/")) return null;
|
|
13
|
+
|
|
14
|
+
return key.substring("@{ctx/".length, key.length - 1);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const getDataSourceProvider = (
|
|
18
|
+
behavior: Behavior
|
|
19
|
+
): BehaviorSubject<string[] | string> | null => {
|
|
20
|
+
if (!behavior) return null;
|
|
21
|
+
|
|
22
|
+
const selection = String(behavior.current_selection);
|
|
23
|
+
const contextKey = parseContextKey(selection);
|
|
24
|
+
|
|
25
|
+
if (contextKey) {
|
|
26
|
+
if (behavior.select_mode === "multi") {
|
|
27
|
+
return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (behavior.select_mode === "single") {
|
|
31
|
+
return StorageSingleValueProvider.getProvider(contextKey).getObservable();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (behavior.selection_source === "@{push/topics}") {
|
|
36
|
+
return PushTopicManager.getInstance().getEntryObservable();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
43
|
+
const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
|
|
44
|
+
const player = usePlayer();
|
|
45
|
+
|
|
46
|
+
const triggerUpdate = () => setLastUpdate(Date.now());
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!behavior) return;
|
|
50
|
+
|
|
51
|
+
const dataSource = getDataSourceProvider(behavior);
|
|
52
|
+
|
|
53
|
+
if (dataSource) {
|
|
54
|
+
const subscription = dataSource.subscribe(triggerUpdate);
|
|
55
|
+
|
|
56
|
+
return () => subscription.unsubscribe();
|
|
57
|
+
}
|
|
58
|
+
}, [behavior]);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!behavior || !player || behavior.selection_source !== "now_playing") {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const subscription = player.getEntryObservable().subscribe(triggerUpdate);
|
|
66
|
+
|
|
67
|
+
return () => subscription.unsubscribe();
|
|
68
|
+
}, [behavior, player]);
|
|
69
|
+
|
|
70
|
+
return lastUpdate;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// We cant use async in this function (its inside render),
|
|
74
|
+
// so we rely on useBehaviorUpdate to update current value and trigger re-render
|
|
75
|
+
export const isCellSelected = (
|
|
76
|
+
item: ZappEntry,
|
|
77
|
+
behavior?: Behavior
|
|
78
|
+
): boolean => {
|
|
79
|
+
if (!behavior) return false;
|
|
80
|
+
|
|
81
|
+
const id = behavior.selector ? get(item, behavior.selector) : item.id;
|
|
82
|
+
|
|
83
|
+
if (behavior.selection_source === "now_playing") {
|
|
84
|
+
const player = playerManager.getActivePlayer();
|
|
85
|
+
|
|
86
|
+
return player?.entry?.id === id;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (behavior.selection_source === "@{push/topics}") {
|
|
90
|
+
if (behavior.select_mode === "single") {
|
|
91
|
+
masterCellLogger.warning(
|
|
92
|
+
"Unexpected single selection mode for push topics"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const tags = PushTopicManager.getInstance().getRegisteredTags();
|
|
97
|
+
|
|
98
|
+
return tags.includes(String(id));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const selection = String(behavior.current_selection);
|
|
102
|
+
const contextKey = parseContextKey(selection);
|
|
103
|
+
|
|
104
|
+
if (contextKey) {
|
|
105
|
+
if (behavior.select_mode === "single") {
|
|
106
|
+
const selectedItem =
|
|
107
|
+
StorageSingleValueProvider.getProvider(contextKey)?.getValue();
|
|
108
|
+
|
|
109
|
+
return selectedItem === String(id);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (behavior.select_mode === "multi") {
|
|
113
|
+
const selectedItems =
|
|
114
|
+
StorageMultiSelectProvider.getProvider(contextKey)?.getSelectedItems();
|
|
115
|
+
|
|
116
|
+
return selectedItems?.includes(String(id));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (behavior.select_mode === "single") {
|
|
121
|
+
return behavior.current_selection === id;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (
|
|
125
|
+
behavior.select_mode === "multi" &&
|
|
126
|
+
Array.isArray(behavior.current_selection)
|
|
127
|
+
) {
|
|
128
|
+
const currentSelection: string[] = behavior.current_selection.map(
|
|
129
|
+
(item): string => String(item)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return currentSelection.includes(String(id));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false;
|
|
136
|
+
};
|