@applicaster/zapp-react-native-ui-components 13.0.0-rc.99 → 14.0.0-alpha.1235043154
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/AnimatedInOut/index.tsx +5 -3
- package/Components/AudioPlayer/index.tsx +15 -0
- package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
- package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
- package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
- package/Components/AudioPlayer/mobile/index.tsx +18 -0
- package/Components/AudioPlayer/tv/Artwork.tsx +40 -0
- package/Components/AudioPlayer/{AudioPlayerLayout.tsx → tv/Layout.tsx} +37 -79
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +2 -1
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +12 -9
- package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +12 -9
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +9 -4
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +170 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -1
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -1
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +3 -6
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +14 -70
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/Focusable/FocusableTvOS.tsx +3 -3
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -2
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
- package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
- package/Components/HandlePlayable/HandlePlayable.tsx +14 -8
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +1 -0
- package/Components/MasterCell/elementMapper.tsx +1 -2
- package/Components/ModalComponent/BottomSheetModalContent.tsx +32 -46
- package/Components/ModalComponent/Button/index.tsx +25 -29
- package/Components/ModalComponent/Header/index.tsx +9 -8
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +26 -43
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +7 -4
- package/Components/River/RiverItem.tsx +8 -4
- package/Components/River/TV/River.tsx +0 -3
- package/Components/River/TV/withTVEventHandler.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +3 -1
- package/Components/RouteManager/TestId.tsx +1 -5
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +0 -1
- package/Components/RouteManager/__tests__/testId.test.js +0 -4
- package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
- package/Components/Screen/__tests__/Screen.test.tsx +22 -14
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +16 -15
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
- package/Components/VideoLive/animationUtils.ts +3 -3
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +1 -2
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +1 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +3 -9
- package/Components/VideoModal/PlayerWrapper.tsx +9 -19
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +60 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +17 -55
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -26
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
- package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
- package/index.d.ts +0 -1
- package/package.json +5 -7
- package/Components/AudioPlayer/Artwork.tsx +0 -35
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- package/Decorators/Navigator/__tests__/react-router-native-mock.js +0 -11
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +0 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/channel.test.js.snap +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render } from "@testing-library/react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { AudioPlayerTV } from "..";
|
|
5
|
+
|
|
6
|
+
jest.mock("@applicaster/zapp-react-native-utils/audioPlayerUtils", () => ({
|
|
7
|
+
useArtworkImage: jest.fn(() => "artwork_url"),
|
|
8
|
+
}));
|
|
5
9
|
|
|
6
10
|
const audioPlayerProps = {
|
|
7
11
|
audio_item: {
|
|
@@ -45,9 +49,9 @@ const audioPlayerProps = {
|
|
|
45
49
|
styles: {},
|
|
46
50
|
};
|
|
47
51
|
|
|
48
|
-
describe("<
|
|
52
|
+
describe("<AudioPlayerTV />", () => {
|
|
49
53
|
it("renders correctly", () => {
|
|
50
|
-
const { toJSON } = render(<
|
|
54
|
+
const { toJSON } = render(<AudioPlayerTV {...audioPlayerProps} />);
|
|
51
55
|
expect(toJSON()).toMatchSnapshot();
|
|
52
56
|
});
|
|
53
57
|
});
|
|
@@ -2,11 +2,8 @@ const defaults = {
|
|
|
2
2
|
audio_player_title_color: "white",
|
|
3
3
|
audio_player_summary_color: "white",
|
|
4
4
|
audio_player_background_color: "black",
|
|
5
|
-
|
|
5
|
+
audio_player_background_image: undefined,
|
|
6
6
|
audio_player_rtl: false,
|
|
7
|
-
magic_background: false,
|
|
8
|
-
audio_player_background_image_query: "",
|
|
9
|
-
audio_player_background_image_default_color: "",
|
|
10
7
|
};
|
|
11
8
|
|
|
12
9
|
export function getPropertyFromEntryOrConfig({ entry, plugin_configuration }) {
|
|
@@ -28,14 +25,14 @@ export function getPropertyFromEntryOrConfig({ entry, plugin_configuration }) {
|
|
|
28
25
|
const LTR = {
|
|
29
26
|
flexDirection: "row",
|
|
30
27
|
justifyContent: "flex-start",
|
|
31
|
-
textAlign: "
|
|
28
|
+
textAlign: "left",
|
|
32
29
|
alignItems: "flex-end",
|
|
33
30
|
};
|
|
34
31
|
|
|
35
32
|
const RTL = {
|
|
36
33
|
flexDirection: "row-reverse",
|
|
37
34
|
justifyContent: "flex-end",
|
|
38
|
-
textAlign: "
|
|
35
|
+
textAlign: "right",
|
|
39
36
|
alignItems: "flex-start",
|
|
40
37
|
};
|
|
41
38
|
|
|
@@ -1,64 +1,24 @@
|
|
|
1
1
|
import React, { useCallback, useMemo } from "react";
|
|
2
2
|
|
|
3
3
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
+
import { useArtworkImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { AudioPlayerTVLayout } from "./Layout";
|
|
6
7
|
|
|
7
|
-
import { AudioPlayerLayout } from "./AudioPlayerLayout";
|
|
8
8
|
import { Channel } from "./Channel";
|
|
9
9
|
import { Title } from "./Title";
|
|
10
10
|
import { Summary } from "./Summary";
|
|
11
11
|
import { Runtime } from "./Runtime";
|
|
12
12
|
import { getPropertyFromEntryOrConfig } from "./helpers";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
audio_player_artwork_aspect_ratio?: string;
|
|
19
|
-
audio_player_background_image?: string;
|
|
20
|
-
audio_player_background_color?: string;
|
|
21
|
-
audio_player_channel_icon?: string;
|
|
22
|
-
audio_player_title_color?: string;
|
|
23
|
-
audio_player_summary_color?: string;
|
|
24
|
-
audio_player_rtl?: boolean;
|
|
25
|
-
magic_background?: boolean;
|
|
26
|
-
audio_player_background_image_query?: string;
|
|
27
|
-
audio_player_background_image_default_color?: string;
|
|
28
|
-
start_time?: string;
|
|
29
|
-
end_time?: string;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
plugin_configuration: {
|
|
33
|
-
audio_player_background_color?: string;
|
|
34
|
-
audio_player_title_color?: string;
|
|
35
|
-
audio_player_summary_color?: string;
|
|
36
|
-
audio_player_rtl?: string;
|
|
37
|
-
magic_background?: string;
|
|
38
|
-
audio_player_background_image_query?: string;
|
|
39
|
-
audio_player_background_image_default_color?: string;
|
|
40
|
-
audio_player_background_image?: string;
|
|
41
|
-
audio_player_artwork_aspect_ratio?: string;
|
|
42
|
-
lg_tv_audio_player_title_font_family?: string;
|
|
43
|
-
lg_tv_audio_player_title_font_size?: number;
|
|
44
|
-
lg_tv_audio_player_summary_font_family?: string;
|
|
45
|
-
lg_tv_audio_player_summary_font_size?: number;
|
|
46
|
-
samsung_tv_audio_player_title_font_family?: string;
|
|
47
|
-
samsung_tv_audio_player_title_font_size?: number;
|
|
48
|
-
samsung_tv_audio_player_summary_font_family?: string;
|
|
49
|
-
samsung_tv_audio_player_summary_font_size?: number;
|
|
50
|
-
tv_os_audio_player_title_font_family?: string;
|
|
51
|
-
tv_os_audio_player_title_font_size?: number;
|
|
52
|
-
tv_os_audio_player_summary_font_family?: string;
|
|
53
|
-
tv_os_audio_player_summary_font_size?: number;
|
|
54
|
-
};
|
|
55
|
-
style?: ViewStyle;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export function AudioPlayer(props: Props) {
|
|
59
|
-
const { audio_item, plugin_configuration, style } = props;
|
|
13
|
+
|
|
14
|
+
import { Props } from "../types";
|
|
15
|
+
|
|
16
|
+
export function AudioPlayerTV(props: Props) {
|
|
17
|
+
const { audio_item, plugin_configuration, style = {} } = props;
|
|
60
18
|
const { extensions, title, summary } = audio_item;
|
|
61
19
|
|
|
20
|
+
const artwork = useArtworkImage(audio_item);
|
|
21
|
+
|
|
62
22
|
const getProp = useCallback(
|
|
63
23
|
getPropertyFromEntryOrConfig({
|
|
64
24
|
entry: audio_item,
|
|
@@ -68,23 +28,14 @@ export function AudioPlayer(props: Props) {
|
|
|
68
28
|
);
|
|
69
29
|
|
|
70
30
|
const config = useMemo(() => {
|
|
71
|
-
// Checking if we are
|
|
31
|
+
// Checking if we are receiving items from the DSP
|
|
72
32
|
const titleColor = getProp("audio_player_title_color");
|
|
73
33
|
const summaryColor = getProp("audio_player_summary_color");
|
|
74
34
|
const backgroundColor = getProp("audio_player_background_color");
|
|
75
35
|
const backgroundImage = getProp("audio_player_background_image");
|
|
76
|
-
const artworkAspectRatio = getProp("audio_player_artwork_aspect_ratio");
|
|
77
36
|
const channelIcon = getProp("audio_player_channel_icon");
|
|
78
37
|
const rtlFlag = getProp("audio_player_rtl");
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
const audioPlayerBackgroundImageQuery = getProp(
|
|
82
|
-
"audio_player_background_image_query"
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
const audioPlayerBackgroundImageDefaultColor = getProp(
|
|
86
|
-
"audio_player_background_image_default_color"
|
|
87
|
-
);
|
|
38
|
+
const artworkBorderRadius = getProp("audio_player_artwork_border_radius");
|
|
88
39
|
|
|
89
40
|
const isRTL = rtlFlag === "1" || rtlFlag === "true" || rtlFlag === true;
|
|
90
41
|
|
|
@@ -160,24 +111,17 @@ export function AudioPlayer(props: Props) {
|
|
|
160
111
|
summaryFontSize,
|
|
161
112
|
runTimeFontFamily,
|
|
162
113
|
runTimeFontSize,
|
|
163
|
-
artworkAspectRatio,
|
|
164
114
|
channelIcon,
|
|
165
|
-
|
|
166
|
-
audioPlayerBackgroundImageQuery,
|
|
167
|
-
audioPlayerBackgroundImageDefaultColor,
|
|
115
|
+
artworkBorderRadius,
|
|
168
116
|
};
|
|
169
117
|
}, [getProp]);
|
|
170
118
|
|
|
171
|
-
const artwork = imageSrcFromMediaItem(audio_item, [
|
|
172
|
-
config?.artworkAspectRatio,
|
|
173
|
-
]);
|
|
174
|
-
|
|
175
119
|
return (
|
|
176
|
-
<
|
|
120
|
+
<AudioPlayerTVLayout artwork={artwork} config={config} style={style}>
|
|
177
121
|
<Channel srcImage={config?.channelIcon} config={config} />
|
|
178
122
|
<Title title={title} config={config} />
|
|
179
123
|
<Summary summary={summary} config={config} />
|
|
180
124
|
<Runtime {...extensions} config={config} />
|
|
181
|
-
</
|
|
125
|
+
</AudioPlayerTVLayout>
|
|
182
126
|
);
|
|
183
127
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ViewStyle } from "react-native";
|
|
2
|
+
|
|
3
|
+
export type Props = {
|
|
4
|
+
audio_item: ZappEntry & {
|
|
5
|
+
extensions?: {
|
|
6
|
+
audio_player_artwork_aspect_ratio?: string;
|
|
7
|
+
audio_player_background_image?: string;
|
|
8
|
+
audio_player_background_color?: string;
|
|
9
|
+
audio_player_channel_icon?: string;
|
|
10
|
+
audio_player_title_color?: string;
|
|
11
|
+
audio_player_summary_color?: string;
|
|
12
|
+
audio_player_rtl?: boolean;
|
|
13
|
+
audio_player_background_image_default_color?: string;
|
|
14
|
+
start_time?: string;
|
|
15
|
+
end_time?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
plugin_configuration: {
|
|
19
|
+
audio_player_background_color?: string;
|
|
20
|
+
audio_player_title_color?: string;
|
|
21
|
+
audio_player_summary_color?: string;
|
|
22
|
+
audio_player_rtl?: string;
|
|
23
|
+
audio_player_background_image_default_color?: string;
|
|
24
|
+
audio_player_background_image?: string;
|
|
25
|
+
audio_player_artwork_aspect_ratio?: string;
|
|
26
|
+
lg_tv_audio_player_title_font_family?: string;
|
|
27
|
+
lg_tv_audio_player_title_font_size?: number;
|
|
28
|
+
lg_tv_audio_player_summary_font_family?: string;
|
|
29
|
+
lg_tv_audio_player_summary_font_size?: number;
|
|
30
|
+
samsung_tv_audio_player_title_font_family?: string;
|
|
31
|
+
samsung_tv_audio_player_title_font_size?: number;
|
|
32
|
+
samsung_tv_audio_player_summary_font_family?: string;
|
|
33
|
+
samsung_tv_audio_player_summary_font_size?: number;
|
|
34
|
+
tv_os_audio_player_title_font_family?: string;
|
|
35
|
+
tv_os_audio_player_title_font_size?: number;
|
|
36
|
+
tv_os_audio_player_summary_font_family?: string;
|
|
37
|
+
tv_os_audio_player_summary_font_size?: number;
|
|
38
|
+
};
|
|
39
|
+
style?: ViewStyle;
|
|
40
|
+
};
|
|
@@ -16,9 +16,9 @@ function noop() {}
|
|
|
16
16
|
type Props = {
|
|
17
17
|
id: string;
|
|
18
18
|
groupId: string;
|
|
19
|
-
onPress?: (nativeEvent:
|
|
20
|
-
onFocus?: (nativeEvent:
|
|
21
|
-
onBlur?: (nativeEvent:
|
|
19
|
+
onPress?: (nativeEvent: any) => void;
|
|
20
|
+
onFocus?: (nativeEvent: any) => void;
|
|
21
|
+
onBlur?: (nativeEvent: any) => void;
|
|
22
22
|
children: (focused?: boolean) => React.ReactNode;
|
|
23
23
|
isParallaxDisabled: boolean;
|
|
24
24
|
preferredFocus?: boolean;
|
|
@@ -11,6 +11,7 @@ import { allSettled } from "promise";
|
|
|
11
11
|
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
12
12
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
13
13
|
import { ScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext";
|
|
14
|
+
import { useEventAlerts } from "./utils/useEventAlerts";
|
|
14
15
|
|
|
15
16
|
const { log_info } = createLogger({
|
|
16
17
|
category: "ScreenContainer",
|
|
@@ -29,7 +30,6 @@ export const GeneralContentScreen = ({
|
|
|
29
30
|
isScreenWrappedInContainer,
|
|
30
31
|
componentsMapExtraProps = {},
|
|
31
32
|
focused,
|
|
32
|
-
extraOffset,
|
|
33
33
|
parentFocus,
|
|
34
34
|
containerHeight,
|
|
35
35
|
preferredFocus = false,
|
|
@@ -103,6 +103,8 @@ export const GeneralContentScreen = ({
|
|
|
103
103
|
[typeof cellTapAction === "function" ? cellTapAction : onCellTapAction]
|
|
104
104
|
);
|
|
105
105
|
|
|
106
|
+
useEventAlerts(screenData);
|
|
107
|
+
|
|
106
108
|
if (!isReady || isNilOrEmpty(components || uiComponents)) return null;
|
|
107
109
|
|
|
108
110
|
return (
|
|
@@ -119,7 +121,6 @@ export const GeneralContentScreen = ({
|
|
|
119
121
|
isScreenWrappedInContainer={isScreenWrappedInContainer}
|
|
120
122
|
parentFocus={parentFocus}
|
|
121
123
|
focused={focused}
|
|
122
|
-
extraOffset={extraOffset}
|
|
123
124
|
containerHeight={containerHeight}
|
|
124
125
|
preferredFocus={preferredFocus}
|
|
125
126
|
{...componentsMapExtraProps}
|
|
@@ -3,8 +3,10 @@ import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
|
|
|
3
3
|
import { useEffect, useMemo } from "react";
|
|
4
4
|
import { useDispatch } from "react-redux";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
useLayoutPresets,
|
|
8
|
+
useZappPipesFeeds,
|
|
9
|
+
} from "@applicaster/zapp-react-native-redux/hooks";
|
|
8
10
|
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
9
11
|
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
12
|
import { Categories } from "./logger";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { showAlertDialog } from "@applicaster/zapp-react-native-utils/alertUtils";
|
|
3
|
+
import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "@applicaster/zapp-react-native-utils/actionsExecutor/consts";
|
|
4
|
+
import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
5
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
6
|
+
import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
|
|
7
|
+
|
|
8
|
+
export const useEventAlerts = (screenData: ZappRiver) => {
|
|
9
|
+
const localizations = useLocalizedStrings({
|
|
10
|
+
localizations: screenData?.localizations || {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const isActive = useIsScreenActive();
|
|
14
|
+
|
|
15
|
+
const onMaxTagsReached = React.useCallback(() => {
|
|
16
|
+
// We can't skip subscribe hook call, so we have to check.
|
|
17
|
+
if (!isActive || !localizations?.msg_maximum_selection_reached_message) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
showAlertDialog({
|
|
22
|
+
title: "",
|
|
23
|
+
message: localizations.msg_maximum_selection_reached_message,
|
|
24
|
+
okButtonText:
|
|
25
|
+
localizations.msg_maximum_selection_reached_message_ok_button || "OK",
|
|
26
|
+
});
|
|
27
|
+
}, [localizations, isActive]);
|
|
28
|
+
|
|
29
|
+
useSubscriberFor(TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT, onMaxTagsReached);
|
|
30
|
+
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
14
14
|
import { PlayerContainer } from "../PlayerContainer";
|
|
15
15
|
import { useModalSize } from "../VideoModal/hooks";
|
|
16
|
+
import { ViewStyle } from "react-native";
|
|
16
17
|
|
|
17
18
|
type Props = {
|
|
18
19
|
item: ZappEntry;
|
|
@@ -140,14 +141,19 @@ export function HandlePlayable({
|
|
|
140
141
|
const modalSize = useModalSize();
|
|
141
142
|
|
|
142
143
|
const style = React.useMemo(
|
|
143
|
-
() =>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
() =>
|
|
145
|
+
({
|
|
146
|
+
width: isModal
|
|
147
|
+
? modalSize.width
|
|
148
|
+
: mode === "PIP"
|
|
149
|
+
? "100%"
|
|
150
|
+
: screenWidth,
|
|
151
|
+
height: isModal
|
|
152
|
+
? modalSize.height
|
|
153
|
+
: mode === "PIP"
|
|
154
|
+
? "100%"
|
|
155
|
+
: screenHeight,
|
|
156
|
+
}) as ViewStyle,
|
|
151
157
|
[screenWidth, screenHeight, modalSize, isModal, mode]
|
|
152
158
|
);
|
|
153
159
|
|
|
@@ -73,7 +73,6 @@ export function elementMapper(
|
|
|
73
73
|
: {};
|
|
74
74
|
|
|
75
75
|
const componentProps = {
|
|
76
|
-
key,
|
|
77
76
|
style,
|
|
78
77
|
skipButtons: otherProps?.skipButtons,
|
|
79
78
|
emitAsyncElementRegistrate: otherProps?.emitAsyncElementRegistrate,
|
|
@@ -91,7 +90,7 @@ export function elementMapper(
|
|
|
91
90
|
const fn = mapElementWithKey(elementMapper(components, otherProps));
|
|
92
91
|
|
|
93
92
|
return (
|
|
94
|
-
<Component {...componentProps}>
|
|
93
|
+
<Component key={key} {...componentProps}>
|
|
95
94
|
{focusableTypes.has(type) && elements.length > 0
|
|
96
95
|
? elements.map(fn)
|
|
97
96
|
: null}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
3
|
-
useEffect,
|
|
4
|
-
useMemo,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react";
|
|
8
|
-
import { View, LayoutChangeEvent, ScrollView } from "react-native";
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { View, ScrollView } from "react-native";
|
|
9
3
|
import { Button } from "./Button";
|
|
10
4
|
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
5
|
import { ItemProps } from "./Button/Item";
|
|
@@ -15,7 +9,8 @@ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
|
15
9
|
|
|
16
10
|
import type { PluginConfiguration } from "./";
|
|
17
11
|
|
|
18
|
-
import { ModalHeader } from "./Header";
|
|
12
|
+
import { ModalHeader as DefaultModalHeader } from "./Header";
|
|
13
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
19
14
|
|
|
20
15
|
type ModalComponentProps = {
|
|
21
16
|
items: any[];
|
|
@@ -27,6 +22,7 @@ type ModalComponentProps = {
|
|
|
27
22
|
title?: string;
|
|
28
23
|
maxHeight?: number;
|
|
29
24
|
dismiss: () => void;
|
|
25
|
+
headerComponent?: React.ComponentType;
|
|
30
26
|
buttonComponent?: React.ComponentType;
|
|
31
27
|
iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
|
|
32
28
|
itemProps?:
|
|
@@ -48,33 +44,25 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
48
44
|
const {
|
|
49
45
|
items,
|
|
50
46
|
currentRoute,
|
|
51
|
-
maxHeight,
|
|
52
47
|
current_selection = null,
|
|
53
48
|
onPress,
|
|
54
49
|
dismiss,
|
|
55
50
|
summary,
|
|
56
51
|
title,
|
|
52
|
+
headerComponent: ModalHeader = DefaultModalHeader,
|
|
57
53
|
buttonComponent: ButtonComponent = Button,
|
|
58
|
-
getSelectedItemIcon = (
|
|
59
|
-
|
|
54
|
+
getSelectedItemIcon = ({
|
|
55
|
+
modal_bottom_sheet_item_selected_icon,
|
|
56
|
+
}: BaseThemePropertiesMobile) => modal_bottom_sheet_item_selected_icon,
|
|
60
57
|
getDefaultItemIcon = () => null,
|
|
61
58
|
iconPlacement,
|
|
62
59
|
} = props;
|
|
63
60
|
|
|
64
|
-
const [headerHeight, setHeaderHeight] = useState(0);
|
|
65
61
|
const route = useRef(currentRoute);
|
|
66
62
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
67
63
|
const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
|
|
68
64
|
const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
|
|
69
65
|
|
|
70
|
-
const maxContentHeight = maxHeight
|
|
71
|
-
? maxHeight - headerHeight - paddingTop
|
|
72
|
-
: undefined;
|
|
73
|
-
|
|
74
|
-
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
75
|
-
setHeaderHeight(event.nativeEvent.layout.height);
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
66
|
useEffect(() => {
|
|
79
67
|
if (currentRoute !== route.current) {
|
|
80
68
|
props.dismiss();
|
|
@@ -101,46 +89,44 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
101
89
|
[onPress, dismiss]
|
|
102
90
|
);
|
|
103
91
|
|
|
92
|
+
const bottomInset = useSafeAreaInsets().bottom;
|
|
93
|
+
|
|
104
94
|
return (
|
|
105
95
|
<View
|
|
106
96
|
style={{
|
|
107
|
-
|
|
108
|
-
paddingTop,
|
|
97
|
+
maxHeight: props.maxHeight,
|
|
98
|
+
paddingTop: paddingTop,
|
|
109
99
|
}}
|
|
110
100
|
>
|
|
111
101
|
<ModalHeader
|
|
112
|
-
width={props.width}
|
|
113
102
|
dismiss={dismiss}
|
|
114
103
|
configuration={theme}
|
|
115
|
-
onLayout={onHeaderLayout}
|
|
116
104
|
summary={summary}
|
|
117
105
|
title={title}
|
|
118
106
|
/>
|
|
119
107
|
<ScrollView
|
|
120
|
-
bounces={false}
|
|
121
|
-
style={{ maxHeight: maxContentHeight }}
|
|
122
108
|
contentContainerStyle={{
|
|
123
|
-
paddingBottom,
|
|
124
|
-
paddingTop,
|
|
109
|
+
paddingBottom: paddingBottom + bottomInset,
|
|
125
110
|
}}
|
|
126
111
|
>
|
|
127
|
-
{items.map((item, index) =>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
112
|
+
{items.map((item, index) =>
|
|
113
|
+
item ? (
|
|
114
|
+
<ButtonComponent
|
|
115
|
+
key={index}
|
|
116
|
+
configuration={theme}
|
|
117
|
+
selectedItem={current_selection}
|
|
118
|
+
item={item}
|
|
119
|
+
onPress={handlePress}
|
|
120
|
+
label={theme[item?.label] ?? item?.label}
|
|
121
|
+
iconBaseProps={iconBaseProps}
|
|
122
|
+
itemBaseProps={itemBaseProps}
|
|
123
|
+
labelBaseProps={labelBaseProps}
|
|
124
|
+
selectedItemIcon={getSelectedItemIcon(theme)}
|
|
125
|
+
defaultItemIcon={getDefaultItemIcon(theme)}
|
|
126
|
+
iconPlacement={iconPlacement}
|
|
127
|
+
/>
|
|
128
|
+
) : null
|
|
129
|
+
)}
|
|
144
130
|
</ScrollView>
|
|
145
131
|
</View>
|
|
146
132
|
);
|
|
@@ -7,7 +7,6 @@ import { defaultSelectedAsset } from "./assets";
|
|
|
7
7
|
|
|
8
8
|
type ButtonProps = {
|
|
9
9
|
configuration: any;
|
|
10
|
-
width: number;
|
|
11
10
|
selectedItem?: any;
|
|
12
11
|
item: any; // Adjust type as needed
|
|
13
12
|
onPress: (item: any) => void; // Adjust type as needed
|
|
@@ -33,7 +32,6 @@ export function Button({
|
|
|
33
32
|
item,
|
|
34
33
|
onPress,
|
|
35
34
|
configuration,
|
|
36
|
-
width,
|
|
37
35
|
iconBaseProps,
|
|
38
36
|
itemBaseProps: itemProps,
|
|
39
37
|
labelBaseProps,
|
|
@@ -65,34 +63,32 @@ export function Button({
|
|
|
65
63
|
if (disabled) return null;
|
|
66
64
|
|
|
67
65
|
return (
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
>
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
{iconPlacement === "left" && renderItemIcon}
|
|
66
|
+
<TouchableOpacity
|
|
67
|
+
activeOpacity={1}
|
|
68
|
+
onPress={() => onPress(item)}
|
|
69
|
+
onPressIn={() => setFocused(true)}
|
|
70
|
+
onPressOut={() => setFocused(false)}
|
|
71
|
+
>
|
|
72
|
+
<Item {...itemProps} focused={focused} selected={selected}>
|
|
73
|
+
<View style={styles.label_icon_container}>
|
|
74
|
+
{iconPlacement === "left" && renderItemIcon}
|
|
78
75
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
{label ? (
|
|
77
|
+
<ItemLabel
|
|
78
|
+
{...labelBaseProps}
|
|
79
|
+
label={label ?? null}
|
|
80
|
+
focused={focused}
|
|
81
|
+
selected={selected}
|
|
82
|
+
/>
|
|
83
|
+
) : null}
|
|
84
|
+
</View>
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
</View>
|
|
86
|
+
{selected ? (
|
|
87
|
+
<ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
|
|
88
|
+
) : (
|
|
89
|
+
iconPlacement === "right" && renderItemIcon
|
|
90
|
+
)}
|
|
91
|
+
</Item>
|
|
92
|
+
</TouchableOpacity>
|
|
97
93
|
);
|
|
98
94
|
}
|
|
@@ -8,13 +8,18 @@ import { PluginConfiguration } from "../index";
|
|
|
8
8
|
type Props = {
|
|
9
9
|
dismiss: () => void;
|
|
10
10
|
configuration: PluginConfiguration;
|
|
11
|
-
width: number;
|
|
12
11
|
onLayout?: (event: LayoutChangeEvent) => void;
|
|
13
12
|
summary?: string;
|
|
14
13
|
title?: string;
|
|
15
14
|
};
|
|
16
15
|
|
|
17
16
|
const styles = StyleSheet.create({
|
|
17
|
+
noFlex: {
|
|
18
|
+
flex: 0,
|
|
19
|
+
},
|
|
20
|
+
flex: {
|
|
21
|
+
flex: 1,
|
|
22
|
+
},
|
|
18
23
|
container: {
|
|
19
24
|
flexDirection: "row",
|
|
20
25
|
alignItems: "center",
|
|
@@ -22,7 +27,7 @@ const styles = StyleSheet.create({
|
|
|
22
27
|
});
|
|
23
28
|
|
|
24
29
|
export function ModalHeader(props: Props) {
|
|
25
|
-
const { configuration, dismiss,
|
|
30
|
+
const { configuration, dismiss, onLayout, summary, title } = props;
|
|
26
31
|
|
|
27
32
|
const closeButtonProps = useMemo<CloseButtonProps>(
|
|
28
33
|
() => ({
|
|
@@ -55,15 +60,11 @@ export function ModalHeader(props: Props) {
|
|
|
55
60
|
|
|
56
61
|
return (
|
|
57
62
|
<View onLayout={onLayout} style={styles.container}>
|
|
58
|
-
<View
|
|
59
|
-
style={{
|
|
60
|
-
width: width - buttonsContainerWidth,
|
|
61
|
-
}}
|
|
62
|
-
>
|
|
63
|
+
<View style={styles.flex}>
|
|
63
64
|
{title ? <Title {...titleProps} /> : null}
|
|
64
65
|
{summary ? <Title {...summaryProps} /> : null}
|
|
65
66
|
</View>
|
|
66
|
-
<View style={{ width: buttonsContainerWidth }}>
|
|
67
|
+
<View style={[styles.noFlex, { width: buttonsContainerWidth }]}>
|
|
67
68
|
<CloseButton {...closeButtonProps} />
|
|
68
69
|
</View>
|
|
69
70
|
</View>
|