@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3977160850 → 12.0.0-alpha.4337072244
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Components/BaseFocusable/index.tsx +1 -1
- package/Components/Cell/Cell.tsx +7 -7
- package/Components/Cell/CellWithFocusable.tsx +38 -19
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableGroup/index.tsx +1 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
- package/Components/HookRenderer/index.tsx +1 -3
- package/Components/Image/Image.android.tsx +3 -25
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -10
- package/Components/Layout/TV/__tests__/index.test.tsx +18 -86
- package/Components/Layout/TV/index.tsx +43 -102
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +17 -2
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/utils/index.ts +18 -7
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +64 -31
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +86 -22
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/TV/River.tsx +0 -23
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/RouteManager/index.tsx +2 -2
- package/Components/Screen/TV/hooks/index.ts +3 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +67 -0
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
- package/Components/Screen/TV/index.web.tsx +174 -0
- package/Components/Screen/__tests__/Screen.test.tsx +5 -1
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +14 -0
- package/Components/Screen/index.tsx +48 -28
- package/Components/ScreenResolver/index.tsx +3 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -28
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
- package/Components/VideoModal/PlayerWrapper.tsx +66 -43
- package/Components/VideoModal/VideoModal.tsx +25 -42
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +6 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/utils.ts +3 -3
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +1 -1
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +94 -25
- package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
- package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/events/index.ts +1 -0
- package/package.json +5 -5
- package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
useNavigationPluginData,
|
|
4
|
+
useIsNavBarVisible,
|
|
5
|
+
useRoute,
|
|
6
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
7
|
+
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
8
|
+
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
9
|
+
|
|
10
|
+
type Return =
|
|
11
|
+
| {
|
|
12
|
+
onContent: true;
|
|
13
|
+
onMenu: false;
|
|
14
|
+
}
|
|
15
|
+
| {
|
|
16
|
+
onContent: false;
|
|
17
|
+
onMenu: true;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getInitialFocus = (focusOnContent, isNavBarVisible): Return => {
|
|
21
|
+
if (focusOnContent) {
|
|
22
|
+
return {
|
|
23
|
+
onContent: true,
|
|
24
|
+
onMenu: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!focusOnContent && isNavBarVisible) {
|
|
29
|
+
// put focus on navbar
|
|
30
|
+
return {
|
|
31
|
+
onContent: false,
|
|
32
|
+
onMenu: true,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// we don't have navbar, put focus on content anyway
|
|
37
|
+
return {
|
|
38
|
+
onContent: true,
|
|
39
|
+
onMenu: false,
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const useInitialFocus = (): void => {
|
|
44
|
+
const navigationPluginData = useNavigationPluginData();
|
|
45
|
+
|
|
46
|
+
const focusOnContent = toBooleanWithDefaultFalse(
|
|
47
|
+
navigationPluginData?.rules?.focus_on_content
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const isNavBarVisible = useIsNavBarVisible();
|
|
51
|
+
|
|
52
|
+
const { pathname: currentRoute } = useRoute();
|
|
53
|
+
|
|
54
|
+
React.useEffect(() => {
|
|
55
|
+
const initialFocus = getInitialFocus(focusOnContent, isNavBarVisible);
|
|
56
|
+
|
|
57
|
+
if (initialFocus.onContent) {
|
|
58
|
+
focusManager.setFocusOnContent(currentRoute);
|
|
59
|
+
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (initialFocus.onMenu) {
|
|
64
|
+
focusManager.setFocusOnMenu(currentRoute);
|
|
65
|
+
}
|
|
66
|
+
}, []);
|
|
67
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { isNil } from "ramda";
|
|
3
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
4
|
+
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
5
|
+
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
6
|
+
|
|
7
|
+
export const useRestoreFocus = (): void => {
|
|
8
|
+
const isScreenActive = useIsScreenActive();
|
|
9
|
+
const previousIsScreenActive = usePrevious(isScreenActive);
|
|
10
|
+
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
if (isNil(previousIsScreenActive)) {
|
|
13
|
+
// it's initial mounting of the screen, do nothing here
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!previousIsScreenActive && isScreenActive) {
|
|
18
|
+
// restore focus when we go back from next screen
|
|
19
|
+
focusManager.setInitialFocus();
|
|
20
|
+
}
|
|
21
|
+
}, [previousIsScreenActive, isScreenActive]);
|
|
22
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { last, pathOr } from "ramda";
|
|
3
|
+
import { View, StyleSheet } from "react-native";
|
|
4
|
+
import {
|
|
5
|
+
getNavigationProps,
|
|
6
|
+
getPathAttributes,
|
|
7
|
+
resolveNavigationPlugin,
|
|
8
|
+
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
9
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
10
|
+
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
11
|
+
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
12
|
+
import { useScreenBackgroundColor } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
13
|
+
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
14
|
+
|
|
15
|
+
import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
|
|
16
|
+
import { ScreenResolver } from "../../ScreenResolver";
|
|
17
|
+
import { useInitialFocus, useRestoreFocus } from "./hooks";
|
|
18
|
+
|
|
19
|
+
const styles = StyleSheet.create({
|
|
20
|
+
container: {
|
|
21
|
+
position: "absolute",
|
|
22
|
+
top: 0,
|
|
23
|
+
left: 0,
|
|
24
|
+
right: 0,
|
|
25
|
+
bottom: 0,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
type Components = {
|
|
30
|
+
NavBar: React.ComponentType<any>;
|
|
31
|
+
Background: React.ComponentType<any>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type Props = {
|
|
35
|
+
route: string;
|
|
36
|
+
Components: Components;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const isPlayer = (routeState): boolean => {
|
|
40
|
+
const pluginType = pathOr(
|
|
41
|
+
"unknown_plugin_type",
|
|
42
|
+
["state", "screen", "plugin_type"],
|
|
43
|
+
routeState
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return pluginType === "player";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const getActiveRiver = ({
|
|
50
|
+
screenId,
|
|
51
|
+
screenType,
|
|
52
|
+
routeState,
|
|
53
|
+
rivers,
|
|
54
|
+
fallbackActiveRiver,
|
|
55
|
+
}) => {
|
|
56
|
+
if (rivers[screenId]) {
|
|
57
|
+
if (screenType === "hooks") {
|
|
58
|
+
const navigations = routeState?.state?.entry?.payload?.navigations;
|
|
59
|
+
|
|
60
|
+
if (navigations) {
|
|
61
|
+
return routeState.state.entry.payload;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return routeState?.state?.screen;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// screenId is not presented into rivers, use fallback instead
|
|
69
|
+
return fallbackActiveRiver;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const getNavigations = ({
|
|
73
|
+
screenId,
|
|
74
|
+
screenType,
|
|
75
|
+
routeState,
|
|
76
|
+
rivers,
|
|
77
|
+
fallbackNavigations,
|
|
78
|
+
}) => {
|
|
79
|
+
if (rivers[screenId]) {
|
|
80
|
+
// river presents
|
|
81
|
+
if (screenType === "hooks") {
|
|
82
|
+
const navigations = routeState?.state?.entry?.payload?.navigations;
|
|
83
|
+
|
|
84
|
+
if (navigations) {
|
|
85
|
+
return navigations;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return routeState?.state?.screen?.navigations;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// screenId is not presented into rivers, use fallback instead
|
|
93
|
+
return fallbackNavigations;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const Screen = ({ route, Components }: Props) => {
|
|
97
|
+
if (isNilOrEmpty(route)) {
|
|
98
|
+
throw Error("Required props: route is missing");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const navigator = useNavigation();
|
|
102
|
+
const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
|
|
103
|
+
|
|
104
|
+
const pathAttributes = getPathAttributes({ pathname: route });
|
|
105
|
+
const routeState = navigator.getStackForPathname(route);
|
|
106
|
+
|
|
107
|
+
const { screenType, screenId } = last(pathAttributes);
|
|
108
|
+
|
|
109
|
+
const backgroundColor = useScreenBackgroundColor(screenId);
|
|
110
|
+
|
|
111
|
+
useInitialFocus();
|
|
112
|
+
useRestoreFocus();
|
|
113
|
+
|
|
114
|
+
const activeRiver = getActiveRiver({
|
|
115
|
+
screenId,
|
|
116
|
+
screenType,
|
|
117
|
+
routeState,
|
|
118
|
+
rivers,
|
|
119
|
+
fallbackActiveRiver: navigator.activeRiver,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const navigationProps = getNavigationProps({
|
|
123
|
+
navigator: {
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
activeRiver,
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
screenTitle: routeState.state.entry?.title || routeState.screen?.name,
|
|
128
|
+
},
|
|
129
|
+
category: "menu",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const navigations = getNavigations({
|
|
133
|
+
screenId,
|
|
134
|
+
screenType,
|
|
135
|
+
routeState,
|
|
136
|
+
rivers,
|
|
137
|
+
fallbackNavigations: navigator.activeRiver.navigations,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const menuPlugin = resolveNavigationPlugin({
|
|
141
|
+
category: "menu",
|
|
142
|
+
navigations,
|
|
143
|
+
plugins,
|
|
144
|
+
}) as QuickBrickPlugin;
|
|
145
|
+
|
|
146
|
+
const NavBar = (Components.NavBar ||
|
|
147
|
+
menuPlugin.module) as React.ComponentType<any>;
|
|
148
|
+
|
|
149
|
+
const isNavBarVisible = !isPlayer(routeState);
|
|
150
|
+
|
|
151
|
+
const screenData =
|
|
152
|
+
screenType === "hooks"
|
|
153
|
+
? routeState?.state?.entry
|
|
154
|
+
: routeState?.state?.screen;
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<View style={[styles.container, { backgroundColor }]}>
|
|
158
|
+
<NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
|
|
159
|
+
<NavBar
|
|
160
|
+
groupId={route}
|
|
161
|
+
isVisible={isNavBarVisible}
|
|
162
|
+
menuPlugin={menuPlugin}
|
|
163
|
+
navigationProps={navigationProps}
|
|
164
|
+
/>
|
|
165
|
+
</NavBarContainer>
|
|
166
|
+
<ScreenResolver
|
|
167
|
+
screenType={screenType}
|
|
168
|
+
screenId={screenId}
|
|
169
|
+
screenData={screenData}
|
|
170
|
+
groupId={route}
|
|
171
|
+
/>
|
|
172
|
+
</View>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { act, create } from "react-test-renderer";
|
|
4
4
|
|
|
5
5
|
const Mocked_RouteManager = jest.fn((props) => (
|
|
6
6
|
<View testID="routeManager" {...props} />
|
|
@@ -69,12 +69,16 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
|
69
69
|
isNavBarVisible: mockIsNavBarVisible,
|
|
70
70
|
useRoute: jest.fn(() => ({
|
|
71
71
|
pathname: "/river/testId",
|
|
72
|
+
screenData: { id: "testId" },
|
|
72
73
|
})),
|
|
73
74
|
useNavigation: jest.fn(() => ({
|
|
74
75
|
canGoBack: () => false,
|
|
75
76
|
currentRoute: "/river/testId",
|
|
77
|
+
activeRiver: { id: "testId" },
|
|
78
|
+
screenData: { id: "testId" },
|
|
76
79
|
data: { screen: { id: "testId" } },
|
|
77
80
|
})),
|
|
81
|
+
useIsScreenActive: jest.fn().mockReturnValue(true),
|
|
78
82
|
}));
|
|
79
83
|
|
|
80
84
|
jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
@@ -11,7 +11,9 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
|
|
|
11
11
|
}
|
|
12
12
|
>
|
|
13
13
|
<View
|
|
14
|
+
hasMenu={false}
|
|
14
15
|
id="/river/testId"
|
|
16
|
+
pathname="/river/testId"
|
|
15
17
|
selected="testId"
|
|
16
18
|
testID="navBar"
|
|
17
19
|
title=""
|
|
@@ -19,6 +21,11 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
|
|
|
19
21
|
<View>
|
|
20
22
|
<View
|
|
21
23
|
pathname="/river/testId"
|
|
24
|
+
screenData={
|
|
25
|
+
Object {
|
|
26
|
+
"id": "testId",
|
|
27
|
+
}
|
|
28
|
+
}
|
|
22
29
|
testID="routeManager"
|
|
23
30
|
/>
|
|
24
31
|
</View>
|
|
@@ -36,7 +43,9 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
|
|
|
36
43
|
}
|
|
37
44
|
>
|
|
38
45
|
<View
|
|
46
|
+
hasMenu={false}
|
|
39
47
|
id="/river/testId"
|
|
48
|
+
pathname="/river/testId"
|
|
40
49
|
selected="testId"
|
|
41
50
|
testID="navBar"
|
|
42
51
|
title=""
|
|
@@ -44,6 +53,11 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
|
|
|
44
53
|
<View>
|
|
45
54
|
<View
|
|
46
55
|
pathname="/river/testId"
|
|
56
|
+
screenData={
|
|
57
|
+
Object {
|
|
58
|
+
"id": "testId",
|
|
59
|
+
}
|
|
60
|
+
}
|
|
47
61
|
testID="routeManager"
|
|
48
62
|
/>
|
|
49
63
|
</View>
|
|
@@ -6,7 +6,10 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
6
6
|
|
|
7
7
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
8
8
|
import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getNavigationPropsV2,
|
|
11
|
+
resolveNavigationPlugin,
|
|
12
|
+
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
10
13
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
11
14
|
import {
|
|
12
15
|
useDimensions,
|
|
@@ -14,6 +17,7 @@ import {
|
|
|
14
17
|
useCurrentScreenData,
|
|
15
18
|
useNavbarState,
|
|
16
19
|
useScreenData,
|
|
20
|
+
useNavigation,
|
|
17
21
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
18
22
|
import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
|
|
19
23
|
|
|
@@ -22,6 +26,17 @@ import { RouteManager } from "../RouteManager";
|
|
|
22
26
|
import { useScreenConfiguration } from "../River/useScreenConfiguration";
|
|
23
27
|
import { useScreenOrientationHandler } from "./orientationHandler";
|
|
24
28
|
|
|
29
|
+
const getScreenId = (
|
|
30
|
+
screenData: LegacyNavigationScreenData,
|
|
31
|
+
fallbackRiver: ZappRiver
|
|
32
|
+
) => {
|
|
33
|
+
return screenData?.targetScreen
|
|
34
|
+
? screenData?.targetScreen?.id ?? fallbackRiver.id
|
|
35
|
+
: "screen_id" in screenData
|
|
36
|
+
? screenData.screen_id
|
|
37
|
+
: fallbackRiver.id;
|
|
38
|
+
};
|
|
39
|
+
|
|
25
40
|
function colorIsNotTransparent(color) {
|
|
26
41
|
const layers = R.compose(
|
|
27
42
|
R.map(R.trim),
|
|
@@ -40,14 +55,13 @@ function isValidColor(string) {
|
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
type Props = {
|
|
43
|
-
pathname:
|
|
58
|
+
pathname: unknown;
|
|
44
59
|
screenData: unknown;
|
|
45
|
-
setToggleMenu: () => void;
|
|
46
|
-
setCloseMenu: () => void;
|
|
47
60
|
};
|
|
48
61
|
|
|
49
|
-
export function Screen(
|
|
62
|
+
export function Screen(_props: Props) {
|
|
50
63
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
64
|
+
const navigation = useNavigation();
|
|
51
65
|
const { plugins } = usePickFromState(["plugins"]);
|
|
52
66
|
|
|
53
67
|
// Gets the data for the current screen configuration
|
|
@@ -59,28 +73,38 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
59
73
|
fullDimensions: true,
|
|
60
74
|
});
|
|
61
75
|
|
|
62
|
-
const
|
|
76
|
+
const { screenData, pathname } = useRoute();
|
|
63
77
|
|
|
64
78
|
const currentRiver = useScreenData(
|
|
65
|
-
(
|
|
66
|
-
? (routeData.screenData as ZappRiver)?.targetScreen.id
|
|
67
|
-
: (routeData.screenData as ZappRiver)?.screen_id
|
|
79
|
+
getScreenId(screenData, navigation.activeRiver)
|
|
68
80
|
);
|
|
69
81
|
|
|
70
82
|
const { title } = useNavbarState();
|
|
71
83
|
|
|
72
|
-
const
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
const hasMenu =
|
|
85
|
+
resolveNavigationPlugin({
|
|
86
|
+
category: "menu",
|
|
87
|
+
navigations: currentRiver.navigations,
|
|
88
|
+
plugins,
|
|
89
|
+
})?.identifier === "quick_brick_side_menu";
|
|
90
|
+
|
|
91
|
+
const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
|
|
92
|
+
const props = getNavigationPropsV2({
|
|
93
|
+
currentRiver,
|
|
94
|
+
title,
|
|
95
|
+
category: "nav_bar",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (props) {
|
|
99
|
+
return {
|
|
100
|
+
...props,
|
|
101
|
+
id: pathname,
|
|
102
|
+
pathname: pathname,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return null;
|
|
107
|
+
}, [currentRiver, pathname]);
|
|
84
108
|
|
|
85
109
|
const NavBar = React.useMemo(
|
|
86
110
|
() =>
|
|
@@ -88,12 +112,10 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
88
112
|
"nav_bar",
|
|
89
113
|
currentRiver,
|
|
90
114
|
plugins
|
|
91
|
-
) as React.ComponentType<MobileNavBarPluginProps>,
|
|
115
|
+
) as React.ComponentType<MobileNavBarPluginProps & { hasMenu: boolean }>,
|
|
92
116
|
[]
|
|
93
117
|
);
|
|
94
118
|
|
|
95
|
-
const { screenData, pathname } = routeData;
|
|
96
|
-
|
|
97
119
|
const offlinePlugin = getComponentModule({
|
|
98
120
|
plugins,
|
|
99
121
|
components: {},
|
|
@@ -124,11 +146,9 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
124
146
|
return (
|
|
125
147
|
<ScreenContextProvider pathname={pathname}>
|
|
126
148
|
<View style={style}>
|
|
127
|
-
<NavBar
|
|
128
|
-
{...{ ...(navBarProps as MobileNavBarPluginProps), id: pathname }}
|
|
129
|
-
/>
|
|
149
|
+
{navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
|
|
130
150
|
|
|
131
|
-
<OfflineFallbackScreen screenData={
|
|
151
|
+
<OfflineFallbackScreen screenData={targetScreenData}>
|
|
132
152
|
{/* @TODO RouteManager doesn't use props, can they be removed ? */}
|
|
133
153
|
<RouteManager pathname={pathname} screenData={screenData} />
|
|
134
154
|
</OfflineFallbackScreen>
|
|
@@ -32,12 +32,13 @@ type Props = {
|
|
|
32
32
|
nextFocusLeft?: React.Ref<any>;
|
|
33
33
|
nextFocusUp?: React.Ref<any>;
|
|
34
34
|
};
|
|
35
|
+
groupId?: string;
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export function ScreenResolverComponent(props: Props) {
|
|
38
39
|
useScreenAnalytics(props);
|
|
39
40
|
|
|
40
|
-
const { screenType, screenId, screenData } = props;
|
|
41
|
+
const { screenType, screenId, screenData, groupId } = props;
|
|
41
42
|
|
|
42
43
|
const { hookPlugin } = screenData || {};
|
|
43
44
|
|
|
@@ -81,6 +82,7 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
81
82
|
item={screenData}
|
|
82
83
|
mode={mode === "PIP" ? "PIP" : "FULLSCREEN"}
|
|
83
84
|
isModal={false}
|
|
85
|
+
groupId={groupId}
|
|
84
86
|
/>
|
|
85
87
|
);
|
|
86
88
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
15
15
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
|
|
16
16
|
import { getUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
|
|
17
|
-
import
|
|
17
|
+
import Image from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/Image";
|
|
18
18
|
import { LiveImage, LiveImageManager, LiveImageType } from "./LiveImageManager";
|
|
19
19
|
|
|
20
20
|
import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
|
|
@@ -39,12 +39,13 @@ type Props = {
|
|
|
39
39
|
imageKey?: string;
|
|
40
40
|
screenConfig: Record<string, any>;
|
|
41
41
|
audioMutedByDefault?: boolean;
|
|
42
|
+
uri: string; // cover image url
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
const PlayerLiveImageComponent = (props: Props) => {
|
|
45
46
|
const dimensions = useDimensions("screen", { fullDimensions: true });
|
|
46
47
|
|
|
47
|
-
const { item, style, playerId
|
|
48
|
+
const { item, style, playerId } = props;
|
|
48
49
|
|
|
49
50
|
const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
|
|
50
51
|
const [mode, setMode] = React.useState(LiveImageType.Image);
|
|
@@ -63,24 +64,27 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
63
64
|
*
|
|
64
65
|
* @param type video or image
|
|
65
66
|
*/
|
|
66
|
-
const setModeDebounced = React.useCallback(
|
|
67
|
-
|
|
68
|
-
if (type ===
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const setModeDebounced = React.useCallback(
|
|
68
|
+
(type: LiveImageType) => {
|
|
69
|
+
if (type === LiveImageType.Video) {
|
|
70
|
+
if (type === mode) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
timeoutRef.current = setTimeout(() => {
|
|
75
|
+
setMode(type);
|
|
76
|
+
}, 1000) as unknown as NodeJS.Timeout;
|
|
77
|
+
} else {
|
|
78
|
+
if (timeoutRef.current) {
|
|
79
|
+
clearTimeout(timeoutRef.current);
|
|
80
|
+
timeoutRef.current = null;
|
|
81
|
+
}
|
|
71
82
|
|
|
72
|
-
timeoutRef.current = setTimeout(() => {
|
|
73
83
|
setMode(type);
|
|
74
|
-
}, 1000) as unknown as NodeJS.Timeout;
|
|
75
|
-
} else {
|
|
76
|
-
if (timeoutRef.current) {
|
|
77
|
-
clearTimeout(timeoutRef.current);
|
|
78
|
-
timeoutRef.current = null;
|
|
79
84
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}, [mode]);
|
|
85
|
+
},
|
|
86
|
+
[mode]
|
|
87
|
+
);
|
|
84
88
|
|
|
85
89
|
const { screenConfig, playerPluginId } = props;
|
|
86
90
|
|
|
@@ -100,7 +104,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
100
104
|
return new LiveImage({
|
|
101
105
|
playerId,
|
|
102
106
|
player: playerFactoryItem.controller,
|
|
103
|
-
component: playerFactoryItem?.Component
|
|
107
|
+
component: playerFactoryItem?.Component,
|
|
104
108
|
});
|
|
105
109
|
} else {
|
|
106
110
|
throw new Error("Player factory item is null");
|
|
@@ -111,10 +115,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
111
115
|
liveImageItem.setMode = setModeDebounced;
|
|
112
116
|
}, [setModeDebounced, liveImageItem]);
|
|
113
117
|
|
|
114
|
-
const { start, end } = React.useMemo(
|
|
115
|
-
() => getAutoplaySettings(item),
|
|
116
|
-
[item]
|
|
117
|
-
);
|
|
118
|
+
const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
|
|
118
119
|
|
|
119
120
|
const controller = liveImageItem.getPlayer();
|
|
120
121
|
const player = usePlayer(playerId);
|
|
@@ -239,7 +240,12 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
239
240
|
|
|
240
241
|
const onPositionUpdated = React.useCallback(
|
|
241
242
|
(data) => {
|
|
242
|
-
const normalizedRect = (rect: {
|
|
243
|
+
const normalizedRect = (rect: {
|
|
244
|
+
left: number;
|
|
245
|
+
right: number;
|
|
246
|
+
top: number;
|
|
247
|
+
bottom: number;
|
|
248
|
+
}) => {
|
|
243
249
|
if (!rect) {
|
|
244
250
|
return null;
|
|
245
251
|
}
|
|
@@ -283,6 +289,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
283
289
|
const videoStyles = { ...style, position: "absolute", zIndex: -100 };
|
|
284
290
|
const Player: any = liveImageItem.component || BufferAnimation;
|
|
285
291
|
|
|
292
|
+
// TODO: nice to have - resolve imageKey when imageUrl is not provided
|
|
286
293
|
return (
|
|
287
294
|
<TrackedView
|
|
288
295
|
testId={`tracked-view-${playerId}-${item.title}`}
|
|
@@ -307,11 +314,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
307
314
|
animationConfig={overlayFadeIn}
|
|
308
315
|
staticStyles={style}
|
|
309
316
|
>
|
|
310
|
-
<
|
|
311
|
-
entry={item}
|
|
312
|
-
style={style}
|
|
313
|
-
imageKey={imageKey}
|
|
314
|
-
/>
|
|
317
|
+
<Image {...props} resizeMode="cover" style={style} applyMaxSize />
|
|
315
318
|
</AnimatedInOut>
|
|
316
319
|
}
|
|
317
320
|
</TrackedView>
|