@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4534459584 → 12.0.0-alpha.5062263581
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 +18 -10
- package/Components/AudioPlayer/AudioPlayer.tsx +9 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +5 -5
- package/Components/HandlePlayable/HandlePlayable.tsx +1 -1
- package/Components/HookRenderer/index.tsx +1 -6
- package/Components/Image/Image.android.tsx +4 -1
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -41
- package/Components/Layout/TV/__tests__/index.test.tsx +1 -34
- package/Components/Layout/TV/index.tsx +20 -36
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +8 -10
- package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
- package/Components/ModalComponent/Button/Item.tsx +82 -0
- package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
- package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
- package/Components/ModalComponent/Button/assets.ts +4 -0
- package/Components/ModalComponent/Button/index.tsx +111 -0
- package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
- package/Components/ModalComponent/Header/Title.tsx +70 -0
- package/Components/ModalComponent/Header/assets.ts +4 -0
- package/Components/ModalComponent/Header/index.tsx +71 -0
- package/Components/ModalComponent/Header/utils.ts +79 -0
- package/Components/ModalComponent/index.tsx +38 -0
- package/Components/ModalComponent/utils.ts +126 -0
- package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +4 -7
- package/Components/River/ComponentsMap/ComponentsMap.tsx +25 -0
- package/Components/River/River.tsx +8 -5
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/River/useScreenConfiguration.ts +3 -4
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
- package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
- package/Components/RouteManager/index.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +43 -35
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +10 -6
- package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
- package/Components/Screen/index.tsx +84 -45
- package/Components/Screen/navigationHandler.ts +0 -82
- package/Components/Screen/orientationHandler.ts +1 -1
- package/Components/ScreenResolver/index.tsx +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/VideoLive/LiveImageManager.ts +42 -13
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +79 -73
- package/Components/VideoModal/PlayerDetails.tsx +3 -0
- package/Components/VideoModal/PlayerWrapper.tsx +66 -65
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +4 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +206 -162
- package/Components/VideoModal/hooks/useModalSize.ts +13 -4
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
- package/Components/index.js +2 -0
- package/Contexts/ScreenContext/index.tsx +1 -1
- package/Decorators/RiverResolver/index.tsx +0 -4
- package/Decorators/index.tsx +0 -4
- package/package.json +5 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Animated, EasingFunction, StyleProp, ViewStyle } from "react-native";
|
|
3
|
-
|
|
3
|
+
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
4
|
+
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
4
5
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
5
6
|
|
|
6
7
|
type AnimatedInterpolatedStyle =
|
|
@@ -35,11 +36,16 @@ function getAnimation(config: AnimatedInConfig, phase: "in" | "out") {
|
|
|
35
36
|
return config[phase] || config;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
export function AnimatedInOut(
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
export function AnimatedInOut({
|
|
40
|
+
visible,
|
|
41
|
+
animationConfig,
|
|
42
|
+
staticStyles = {},
|
|
43
|
+
children,
|
|
44
|
+
}: Props) {
|
|
41
45
|
const [animatedValue] = React.useState(new Animated.Value(visible ? 1 : 0));
|
|
42
|
-
const [animating, setAnimating] = React.useState(
|
|
46
|
+
const [animating, setAnimating] = React.useState(undefined);
|
|
47
|
+
|
|
48
|
+
const previousVisible = usePrevious(toBooleanWithDefaultFalse(visible));
|
|
43
49
|
|
|
44
50
|
function startAnimation(toValue, config) {
|
|
45
51
|
if (animating) {
|
|
@@ -55,7 +61,7 @@ export function AnimatedInOut(props: Props) {
|
|
|
55
61
|
delay,
|
|
56
62
|
useNativeDriver: true,
|
|
57
63
|
}).start(() => {
|
|
58
|
-
setAnimating(
|
|
64
|
+
setAnimating(undefined);
|
|
59
65
|
onAnimationEnd();
|
|
60
66
|
});
|
|
61
67
|
|
|
@@ -63,12 +69,14 @@ export function AnimatedInOut(props: Props) {
|
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
React.useEffect(() => {
|
|
66
|
-
if (visible) {
|
|
72
|
+
if (!previousVisible && visible) {
|
|
67
73
|
startAnimation(1.0, getAnimation(animationConfig, "in"));
|
|
68
|
-
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (previousVisible && !visible) {
|
|
69
77
|
startAnimation(0.0, getAnimation(animationConfig, "out"));
|
|
70
78
|
}
|
|
71
|
-
}, [visible,
|
|
79
|
+
}, [visible, previousVisible]);
|
|
72
80
|
|
|
73
81
|
const styles = visible
|
|
74
82
|
? getAnimation(animationConfig, "in").styles
|
|
@@ -77,7 +85,7 @@ export function AnimatedInOut(props: Props) {
|
|
|
77
85
|
return (
|
|
78
86
|
<Animated.View
|
|
79
87
|
renderToHardwareTextureAndroid={animating}
|
|
80
|
-
style={[styles(animatedValue),
|
|
88
|
+
style={[styles(animatedValue), staticStyles]}
|
|
81
89
|
>
|
|
82
90
|
{children}
|
|
83
91
|
</Animated.View>
|
|
@@ -23,6 +23,7 @@ type Props = {
|
|
|
23
23
|
audio_player_summary_color?: string;
|
|
24
24
|
audio_player_rtl?: boolean;
|
|
25
25
|
magic_background?: boolean;
|
|
26
|
+
audio_player_background_image_query?: string;
|
|
26
27
|
start_time?: string;
|
|
27
28
|
end_time?: string;
|
|
28
29
|
};
|
|
@@ -33,6 +34,7 @@ type Props = {
|
|
|
33
34
|
audio_player_summary_color?: string;
|
|
34
35
|
audio_player_rtl?: string;
|
|
35
36
|
magic_background?: string;
|
|
37
|
+
audio_player_background_image_query?: string;
|
|
36
38
|
audio_player_background_image?: string;
|
|
37
39
|
audio_player_artwork_aspect_ratio?: string;
|
|
38
40
|
lg_tv_audio_player_title_font_family?: string;
|
|
@@ -73,6 +75,11 @@ export function AudioPlayer(props: Props) {
|
|
|
73
75
|
const channelIcon = getProp("audio_player_channel_icon");
|
|
74
76
|
const rtlFlag = getProp("audio_player_rtl");
|
|
75
77
|
const magicBackground = getProp("magic_background");
|
|
78
|
+
|
|
79
|
+
const audioPlayerBackgroundImageQuery = getProp(
|
|
80
|
+
"audio_player_background_image_query"
|
|
81
|
+
);
|
|
82
|
+
|
|
76
83
|
const isRTL = rtlFlag === "1" || rtlFlag === "true" || rtlFlag === true;
|
|
77
84
|
|
|
78
85
|
const titleFontFamily = getProp(
|
|
@@ -149,7 +156,8 @@ export function AudioPlayer(props: Props) {
|
|
|
149
156
|
runTimeFontSize,
|
|
150
157
|
artworkAspectRatio,
|
|
151
158
|
channelIcon,
|
|
152
|
-
magicBackground
|
|
159
|
+
magicBackground,
|
|
160
|
+
audioPlayerBackgroundImageQuery,
|
|
153
161
|
};
|
|
154
162
|
}, [getProp]);
|
|
155
163
|
|
|
@@ -5,6 +5,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
|
|
|
5
5
|
config={
|
|
6
6
|
Object {
|
|
7
7
|
"artworkAspectRatio": "1:1",
|
|
8
|
+
"audioPlayerBackgroundImageQuery": "",
|
|
8
9
|
"backgroundColor": "black",
|
|
9
10
|
"backgroundImage": "https://example.com",
|
|
10
11
|
"channelIcon": "https://example.com",
|
|
@@ -26,6 +27,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
|
|
|
26
27
|
config={
|
|
27
28
|
Object {
|
|
28
29
|
"artworkAspectRatio": "1:1",
|
|
30
|
+
"audioPlayerBackgroundImageQuery": "",
|
|
29
31
|
"backgroundColor": "black",
|
|
30
32
|
"backgroundImage": "https://example.com",
|
|
31
33
|
"channelIcon": "https://example.com",
|
|
@@ -47,6 +49,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
|
|
|
47
49
|
config={
|
|
48
50
|
Object {
|
|
49
51
|
"artworkAspectRatio": "1:1",
|
|
52
|
+
"audioPlayerBackgroundImageQuery": "",
|
|
50
53
|
"backgroundColor": "black",
|
|
51
54
|
"backgroundImage": "https://example.com",
|
|
52
55
|
"channelIcon": "https://example.com",
|
|
@@ -68,6 +71,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
|
|
|
68
71
|
config={
|
|
69
72
|
Object {
|
|
70
73
|
"artworkAspectRatio": "1:1",
|
|
74
|
+
"audioPlayerBackgroundImageQuery": "",
|
|
71
75
|
"backgroundColor": "black",
|
|
72
76
|
"backgroundImage": "https://example.com",
|
|
73
77
|
"channelIcon": "https://example.com",
|
|
@@ -96,6 +100,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
|
|
|
96
100
|
config={
|
|
97
101
|
Object {
|
|
98
102
|
"artworkAspectRatio": "1:1",
|
|
103
|
+
"audioPlayerBackgroundImageQuery": "",
|
|
99
104
|
"backgroundColor": "black",
|
|
100
105
|
"backgroundImage": "https://example.com",
|
|
101
106
|
"channelIcon": "https://example.com",
|
|
@@ -52,13 +52,13 @@ export const GeneralContentScreen = ({
|
|
|
52
52
|
React.useState(actionsInitialStateSetters.length === 0);
|
|
53
53
|
|
|
54
54
|
useEffect(() => {
|
|
55
|
-
log_info(
|
|
56
|
-
`ScreenContainer: starting to check river action provider ready, current status: ${riverActionProvidersReady}`,
|
|
57
|
-
{ actionsInitialStateSetters }
|
|
58
|
-
);
|
|
59
|
-
|
|
60
55
|
if (!riverActionProvidersReady) {
|
|
61
56
|
if (actionsInitialStateSetters.length > 0) {
|
|
57
|
+
log_info(
|
|
58
|
+
"ScreenContainer: starting to check river action providers to initialize",
|
|
59
|
+
{ actionsInitialStateSetters }
|
|
60
|
+
);
|
|
61
|
+
|
|
62
62
|
allSettled(actionsInitialStateSetters).finally(() => {
|
|
63
63
|
log_info(
|
|
64
64
|
"ScreenContainer: action provider ready, completed. Starting to present screen"
|
|
@@ -104,7 +104,7 @@ export function HandlePlayable({
|
|
|
104
104
|
const [Player, playerModuleProperties] = getPlayer(item, state);
|
|
105
105
|
|
|
106
106
|
const { module: CastPlugin } =
|
|
107
|
-
findPluginByIdentifier(CHROMECAST_PLUGIN_ID, state.plugins) || {};
|
|
107
|
+
findPluginByIdentifier(CHROMECAST_PLUGIN_ID, state.plugins, true) || {};
|
|
108
108
|
|
|
109
109
|
const [playable, setPlayable] =
|
|
110
110
|
React.useState<Nullable<PlayableComponent>>(null);
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator/";
|
|
4
|
-
import { HookRenderer as HookRendererComponent } from "./HookRenderer";
|
|
5
|
-
|
|
6
|
-
export const HookRenderer = R.compose(withNavigator)(HookRendererComponent);
|
|
1
|
+
export { HookRenderer } from "./HookRenderer";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
3
2
|
import FastImage, {
|
|
4
3
|
FastImageProps,
|
|
5
4
|
} from "@applicaster/react-native-fast-image";
|
|
@@ -15,6 +14,8 @@ export const QBImage = (props: FastImageProps) => {
|
|
|
15
14
|
headers: props.source.headers,
|
|
16
15
|
priority: props.source.priority,
|
|
17
16
|
cache: props.source.cache,
|
|
17
|
+
maxWidth: props.source.maxWidth,
|
|
18
|
+
maxHeight: props.source.maxHeight,
|
|
18
19
|
};
|
|
19
20
|
}, [
|
|
20
21
|
...(typeof props.source === "object"
|
|
@@ -23,6 +24,8 @@ export const QBImage = (props: FastImageProps) => {
|
|
|
23
24
|
props.source?.priority,
|
|
24
25
|
props.source?.cache,
|
|
25
26
|
props.source?.headers,
|
|
27
|
+
props.source?.maxWidth,
|
|
28
|
+
props.source?.maxHeight,
|
|
26
29
|
]
|
|
27
30
|
: []),
|
|
28
31
|
]);
|
|
@@ -14,46 +14,6 @@ exports[`Layout TV renders 1`] = `
|
|
|
14
14
|
<View
|
|
15
15
|
backgroundImageUrl="http://applicaster.com"
|
|
16
16
|
testID="background-component"
|
|
17
|
-
|
|
18
|
-
<View
|
|
19
|
-
style={
|
|
20
|
-
Array [
|
|
21
|
-
Object {
|
|
22
|
-
"position": "absolute",
|
|
23
|
-
"top": 0,
|
|
24
|
-
"width": 1920,
|
|
25
|
-
"zIndex": 10,
|
|
26
|
-
},
|
|
27
|
-
Object {
|
|
28
|
-
"maxHeight": 10,
|
|
29
|
-
},
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
testID="nav-bar-container"
|
|
33
|
-
>
|
|
34
|
-
<View
|
|
35
|
-
isVisible={true}
|
|
36
|
-
menuPlugin={
|
|
37
|
-
Object {
|
|
38
|
-
"module": [Function],
|
|
39
|
-
"name": "resolved-menu-plug",
|
|
40
|
-
"type": "menu",
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
navigationProps={
|
|
44
|
-
Object {
|
|
45
|
-
"assets": undefined,
|
|
46
|
-
"home": undefined,
|
|
47
|
-
"nav_items": undefined,
|
|
48
|
-
"rules": undefined,
|
|
49
|
-
"selected": undefined,
|
|
50
|
-
"styles": undefined,
|
|
51
|
-
"title": "",
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
testID="nav-bar-component"
|
|
55
|
-
/>
|
|
56
|
-
</View>
|
|
57
|
-
</View>
|
|
17
|
+
/>
|
|
58
18
|
</View>
|
|
59
19
|
`;
|
|
@@ -12,19 +12,7 @@ jest.mock("@applicaster/quick-brick-core/App/ActionSetters", () => ({
|
|
|
12
12
|
useRiverInitialState: () => ({}),
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
|
-
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen"
|
|
16
|
-
useCurrentScreenData: jest.fn(() => ({
|
|
17
|
-
navigations: [
|
|
18
|
-
{
|
|
19
|
-
category: "menu",
|
|
20
|
-
navigation_type: "menu",
|
|
21
|
-
styles: {
|
|
22
|
-
hide_secondary_level_menu: false,
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
})),
|
|
27
|
-
}));
|
|
15
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen");
|
|
28
16
|
|
|
29
17
|
const Layout = require("..").default;
|
|
30
18
|
|
|
@@ -125,25 +113,4 @@ describe("Layout TV", () => {
|
|
|
125
113
|
expect(bgComponent.props.testProp).toBe(true);
|
|
126
114
|
});
|
|
127
115
|
});
|
|
128
|
-
|
|
129
|
-
describe("props passed to navbar component", () => {
|
|
130
|
-
it("passes correct props", () => {
|
|
131
|
-
const { getByTestId } = render(
|
|
132
|
-
<Layout
|
|
133
|
-
Components={Components}
|
|
134
|
-
ComponentsExtraProps={{
|
|
135
|
-
NavBar: { testProp: true },
|
|
136
|
-
}}
|
|
137
|
-
>
|
|
138
|
-
<Screen />
|
|
139
|
-
</Layout>,
|
|
140
|
-
{ wrapper }
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const navbarComponent = getByTestId("nav-bar-component");
|
|
144
|
-
expect(navbarComponent.props.isVisible).toBe(isNavBarVisible);
|
|
145
|
-
expect(navbarComponent.props.menuPlugin).toBe(plugins[0]);
|
|
146
|
-
expect(navbarComponent.props.testProp).toBe(true);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
116
|
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
|
-
import {
|
|
5
|
-
useIsNavBarVisible,
|
|
6
|
-
useNavigation,
|
|
7
|
-
} from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
4
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
8
5
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
9
6
|
|
|
10
7
|
import {
|
|
@@ -43,7 +40,7 @@ type Props = {
|
|
|
43
40
|
const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
44
41
|
const navigator = useNavigation();
|
|
45
42
|
const theme = useTheme();
|
|
46
|
-
const { title } = useNavbarState();
|
|
43
|
+
const { title, visible } = useNavbarState();
|
|
47
44
|
const { activeRiver, currentRoute } = navigator;
|
|
48
45
|
|
|
49
46
|
const {
|
|
@@ -80,10 +77,22 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
80
77
|
[]
|
|
81
78
|
);
|
|
82
79
|
|
|
83
|
-
const navBarVisible = useIsNavBarVisible();
|
|
84
|
-
|
|
85
80
|
const [navBarReady, setNavBarReady] = React.useState(false);
|
|
86
81
|
|
|
82
|
+
const navBarContainer = (
|
|
83
|
+
<NavBarContainer isVisible={visible} onReady={setNavBarReady}>
|
|
84
|
+
<NavBar
|
|
85
|
+
ref={ComponentsExtraProps?.NavBar?.ref}
|
|
86
|
+
isVisible={visible && !routeIsPlayerScreen(currentRoute)}
|
|
87
|
+
menuPlugin={menuPlugin}
|
|
88
|
+
navigationProps={navigationProps}
|
|
89
|
+
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
90
|
+
/>
|
|
91
|
+
</NavBarContainer>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const isTVOS = isApplePlatform();
|
|
95
|
+
|
|
87
96
|
if (!appReady) {
|
|
88
97
|
return null;
|
|
89
98
|
}
|
|
@@ -96,18 +105,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
96
105
|
backgroundImageUrl={backgroundImageUrl}
|
|
97
106
|
{...R.omit(["ref"])(ComponentsExtraProps?.Background)}
|
|
98
107
|
>
|
|
99
|
-
{!
|
|
100
|
-
<NavBarContainer isVisible={navBarVisible} onReady={setNavBarReady}>
|
|
101
|
-
<NavBar
|
|
102
|
-
ref={ComponentsExtraProps?.NavBar?.ref}
|
|
103
|
-
isVisible={navBarVisible && !routeIsPlayerScreen(currentRoute)}
|
|
104
|
-
menuPlugin={menuPlugin}
|
|
105
|
-
navigationProps={navigationProps}
|
|
106
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
107
|
-
/>
|
|
108
|
-
</NavBarContainer>
|
|
109
|
-
) : null}
|
|
110
|
-
|
|
108
|
+
{!isTVOS ? navBarContainer : null}
|
|
111
109
|
{navBarReady ? (
|
|
112
110
|
/**
|
|
113
111
|
Need to re-mount this component on each navigation event
|
|
@@ -118,23 +116,9 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
118
116
|
<ScreenContainer>{children}</ScreenContainer>
|
|
119
117
|
</PathnameContext.Provider>
|
|
120
118
|
) : null}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Render NavBarContainer over ScreenContainer to let tvOS native
|
|
125
|
-
focus manager works correctly to focus nav bar items first
|
|
126
|
-
**/
|
|
127
|
-
<NavBarContainer isVisible={navBarVisible} onReady={setNavBarReady}>
|
|
128
|
-
<NavBar
|
|
129
|
-
ref={ComponentsExtraProps?.NavBar?.ref}
|
|
130
|
-
isVisible={navBarVisible && !routeIsPlayerScreen(currentRoute)}
|
|
131
|
-
menuPlugin={menuPlugin}
|
|
132
|
-
navigationProps={navigationProps}
|
|
133
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
134
|
-
/>
|
|
135
|
-
</NavBarContainer>
|
|
136
|
-
) : null}
|
|
137
|
-
|
|
119
|
+
{/** Render NavBarContainer over ScreenContainer to let tvOS native
|
|
120
|
+
focus manager works correctly to focus nav bar items first **/}
|
|
121
|
+
{!isTVOS ? navBarContainer : null}
|
|
138
122
|
<TransitionOverlay />
|
|
139
123
|
</Components.Background>
|
|
140
124
|
</ScreenLayoutContextProvider>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compact,
|
|
3
3
|
ifElseFocusedSelected,
|
|
4
|
+
ifElseSelected,
|
|
4
5
|
} from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
5
6
|
|
|
6
7
|
import { getPositionStyles } from "./utils";
|
|
@@ -12,9 +13,15 @@ type Props = {
|
|
|
12
13
|
value: Function;
|
|
13
14
|
state: string;
|
|
14
15
|
visible?: Boolean;
|
|
16
|
+
isMobile?: Boolean;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
export const CellBadge = ({
|
|
19
|
+
export const CellBadge = ({
|
|
20
|
+
value,
|
|
21
|
+
state,
|
|
22
|
+
visible = true,
|
|
23
|
+
isMobile = false,
|
|
24
|
+
}: Props) => {
|
|
18
25
|
if (!value("cell_badge_switch") || !visible) {
|
|
19
26
|
return null;
|
|
20
27
|
}
|
|
@@ -45,13 +52,19 @@ export const CellBadge = ({ value, state, visible = true }: Props) => {
|
|
|
45
52
|
data: [
|
|
46
53
|
{
|
|
47
54
|
func: () => {
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
return isMobile
|
|
56
|
+
? ifElseSelected(
|
|
57
|
+
state,
|
|
58
|
+
value("cell_badge_selected"),
|
|
59
|
+
value("cell_badge_default")
|
|
60
|
+
)
|
|
61
|
+
: ifElseFocusedSelected(
|
|
62
|
+
state,
|
|
63
|
+
value("cell_badge_focused"),
|
|
64
|
+
value("cell_badge_selected"),
|
|
65
|
+
value("cell_badge_focused_selected"),
|
|
66
|
+
value("cell_badge_default")
|
|
67
|
+
);
|
|
55
68
|
},
|
|
56
69
|
args: [],
|
|
57
70
|
propName: "uri",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { path
|
|
1
|
+
import { path } from "ramda";
|
|
2
2
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
3
3
|
import {
|
|
4
|
+
getColorFromData,
|
|
4
5
|
getKeyForLabel,
|
|
5
6
|
mapSelfAlignment,
|
|
6
7
|
} from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
@@ -48,15 +49,12 @@ export const CollapsibleTextContainer = ({
|
|
|
48
49
|
]),
|
|
49
50
|
{
|
|
50
51
|
func: (data) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
// return default value
|
|
58
|
-
return additionalStyles.backgroundColor;
|
|
59
|
-
}
|
|
52
|
+
return getColorFromData({
|
|
53
|
+
data,
|
|
54
|
+
getValue,
|
|
55
|
+
key: "background_color",
|
|
56
|
+
defaultColor: additionalStyles.backgroundColor,
|
|
57
|
+
});
|
|
60
58
|
},
|
|
61
59
|
propName: "backgroundColor",
|
|
62
60
|
},
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
8
|
+
import { View, LayoutChangeEvent, ScrollView } from "react-native";
|
|
9
|
+
import { Button } from "./Button";
|
|
10
|
+
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
|
+
import { ItemProps } from "./Button/Item";
|
|
12
|
+
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
13
|
+
import {
|
|
14
|
+
defaultItemIconProps,
|
|
15
|
+
defaultItemLabelProps,
|
|
16
|
+
defaultItemProps,
|
|
17
|
+
} from "./utils";
|
|
18
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
19
|
+
|
|
20
|
+
import { ModalHeader } from "./Header";
|
|
21
|
+
|
|
22
|
+
type ModalComponentProps = {
|
|
23
|
+
items: any[];
|
|
24
|
+
current_selection?: any;
|
|
25
|
+
onPress: (item: any) => void;
|
|
26
|
+
width: number;
|
|
27
|
+
currentRoute: boolean;
|
|
28
|
+
summary?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
maxHeight?: number;
|
|
31
|
+
dismiss: () => void;
|
|
32
|
+
buttonComponent?: React.ComponentType;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
36
|
+
const {
|
|
37
|
+
items,
|
|
38
|
+
currentRoute,
|
|
39
|
+
maxHeight,
|
|
40
|
+
current_selection = null,
|
|
41
|
+
onPress,
|
|
42
|
+
dismiss,
|
|
43
|
+
summary,
|
|
44
|
+
title,
|
|
45
|
+
buttonComponent: ButtonComponent = Button,
|
|
46
|
+
} = props;
|
|
47
|
+
|
|
48
|
+
const [headerHeight, setHeaderHeight] = useState(0);
|
|
49
|
+
const route = useRef(currentRoute);
|
|
50
|
+
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
51
|
+
|
|
52
|
+
const maxContentHeight = maxHeight
|
|
53
|
+
? maxHeight - headerHeight - Number(theme.modal_bottom_sheet_padding_top)
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
57
|
+
setHeaderHeight(event.nativeEvent.layout.height);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (currentRoute !== route.current) {
|
|
62
|
+
props.dismiss();
|
|
63
|
+
}
|
|
64
|
+
}, [currentRoute]);
|
|
65
|
+
|
|
66
|
+
const iconBaseProps = useMemo<ItemIconProps>(() => {
|
|
67
|
+
return defaultItemIconProps(theme);
|
|
68
|
+
}, [theme]);
|
|
69
|
+
|
|
70
|
+
const itemBaseProps = useMemo<ItemProps>(() => {
|
|
71
|
+
return defaultItemProps(theme, props.width);
|
|
72
|
+
}, [theme, props.width]);
|
|
73
|
+
|
|
74
|
+
const labelBaseProps = useMemo<ItemLabelProps>(() => {
|
|
75
|
+
return defaultItemLabelProps(theme, props.width);
|
|
76
|
+
}, [theme, props.width]);
|
|
77
|
+
|
|
78
|
+
const handlePress = (item: any) => {
|
|
79
|
+
onPress(item);
|
|
80
|
+
dismiss();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<View
|
|
85
|
+
style={{
|
|
86
|
+
paddingTop: Number(theme.modal_bottom_sheet_padding_top),
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<ModalHeader
|
|
90
|
+
width={props.width}
|
|
91
|
+
dismiss={dismiss}
|
|
92
|
+
configuration={theme}
|
|
93
|
+
onLayout={onHeaderLayout}
|
|
94
|
+
summary={summary}
|
|
95
|
+
title={title}
|
|
96
|
+
/>
|
|
97
|
+
<ScrollView
|
|
98
|
+
bounces={false}
|
|
99
|
+
style={{ maxHeight: maxContentHeight }}
|
|
100
|
+
contentContainerStyle={{
|
|
101
|
+
paddingBottom: Number(theme.modal_bottom_sheet_padding_bottom),
|
|
102
|
+
paddingTop: Number(theme.modal_bottom_sheet_padding_top),
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{items.map((item, index) => (
|
|
106
|
+
<ButtonComponent
|
|
107
|
+
key={index}
|
|
108
|
+
width={props.width}
|
|
109
|
+
configuration={theme}
|
|
110
|
+
selectedItem={current_selection}
|
|
111
|
+
item={item}
|
|
112
|
+
onPress={handlePress}
|
|
113
|
+
iconBaseProps={iconBaseProps}
|
|
114
|
+
itemBaseProps={itemBaseProps}
|
|
115
|
+
labelBaseProps={labelBaseProps}
|
|
116
|
+
/>
|
|
117
|
+
))}
|
|
118
|
+
</ScrollView>
|
|
119
|
+
</View>
|
|
120
|
+
);
|
|
121
|
+
}
|