@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4043183114 → 12.0.0-alpha.4155487673
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/Cell/Cell.tsx +30 -10
- package/Components/Cell/CellWithFocusable.tsx +1 -1
- package/Components/Cell/TvOSCellComponent.tsx +4 -3
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +1 -7
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +57 -0
- package/Components/MasterCell/DefaultComponents/index.ts +2 -0
- package/Components/MasterCell/dataAdapter.ts +21 -7
- package/Components/MasterCell/index.tsx +5 -3
- package/Components/NativeFocusables/{index.ts → index.js} +2 -4
- package/Components/ScreenResolver/index.tsx +6 -11
- package/Components/Transitioner/Transitioner.tsx +17 -15
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +26 -24
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +6 -1
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +5 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +48 -2
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
- package/Decorators/Analytics/{index.tsx → index.js} +11 -11
- package/README.md +13 -1
- package/package.json +5 -5
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { join,
|
|
2
|
+
import { join, merge, path } from "ramda";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
|
|
5
5
|
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
|
|
@@ -14,7 +14,10 @@ import { BaseFocusable } from "../BaseFocusable";
|
|
|
14
14
|
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
15
15
|
|
|
16
16
|
type Props = {
|
|
17
|
-
item:
|
|
17
|
+
item: {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
};
|
|
18
21
|
index: number;
|
|
19
22
|
shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
|
|
20
23
|
shouldScrollVertically: (...args: any) => boolean | null | undefined;
|
|
@@ -30,9 +33,10 @@ type Props = {
|
|
|
30
33
|
id: string;
|
|
31
34
|
};
|
|
32
35
|
selected?: boolean;
|
|
33
|
-
CellRenderer: React.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
CellRenderer: React.ComponentType<{
|
|
37
|
+
item: any;
|
|
38
|
+
state: string;
|
|
39
|
+
}> & { hasFocusableInside: (item: Record<string, string>) => boolean };
|
|
36
40
|
preferredFocus: boolean;
|
|
37
41
|
navigator: {
|
|
38
42
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -63,6 +67,10 @@ type Props = {
|
|
|
63
67
|
behavior: Behavior;
|
|
64
68
|
};
|
|
65
69
|
|
|
70
|
+
type State = {
|
|
71
|
+
hasFocusableInside: boolean;
|
|
72
|
+
};
|
|
73
|
+
|
|
66
74
|
const baseCellStyles = {
|
|
67
75
|
height: "100%",
|
|
68
76
|
display: "flex",
|
|
@@ -74,7 +82,7 @@ const touchableStyles = {
|
|
|
74
82
|
height: "100%",
|
|
75
83
|
} as const;
|
|
76
84
|
|
|
77
|
-
export class CellComponent extends React.Component<Props> {
|
|
85
|
+
export class CellComponent extends React.Component<Props, State> {
|
|
78
86
|
constructor(props) {
|
|
79
87
|
super(props);
|
|
80
88
|
this.onPress = this.onPress.bind(this);
|
|
@@ -84,6 +92,10 @@ export class CellComponent extends React.Component<Props> {
|
|
|
84
92
|
this.hasReceivedFocus = this.hasReceivedFocus.bind(this);
|
|
85
93
|
this.scrollVertically = this.scrollVertically.bind(this);
|
|
86
94
|
this.scrollToIndex = this.scrollToIndex.bind(this);
|
|
95
|
+
|
|
96
|
+
this.state = {
|
|
97
|
+
hasFocusableInside: props.CellRenderer.hasFocusableInside?.(props.item),
|
|
98
|
+
};
|
|
87
99
|
}
|
|
88
100
|
|
|
89
101
|
setScreenLayout(componentAnchorPointY, screenLayout) {
|
|
@@ -139,7 +151,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
139
151
|
|
|
140
152
|
const accessibilityManager = AccessibilityManager.getInstance();
|
|
141
153
|
// Text from DSP should be localized already
|
|
142
|
-
accessibilityManager.readText({ text: title
|
|
154
|
+
accessibilityManager.readText({ text: title });
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
157
|
}
|
|
@@ -188,6 +200,16 @@ export class CellComponent extends React.Component<Props> {
|
|
|
188
200
|
return !isFocusable ? false : focused || focusableFocused;
|
|
189
201
|
}
|
|
190
202
|
|
|
203
|
+
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
204
|
+
if (prevProps.item !== this.props.item) {
|
|
205
|
+
this.setState({
|
|
206
|
+
hasFocusableInside: this.props.CellRenderer.hasFocusableInside?.(
|
|
207
|
+
this.props.item
|
|
208
|
+
),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
191
213
|
render() {
|
|
192
214
|
const {
|
|
193
215
|
item,
|
|
@@ -216,9 +238,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
216
238
|
this.onFocus(focusable, mouse);
|
|
217
239
|
};
|
|
218
240
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (hasFocusableInside) {
|
|
241
|
+
if (this.state.hasFocusableInside) {
|
|
222
242
|
return (
|
|
223
243
|
<CellWithFocusable
|
|
224
244
|
CellRenderer={CellRenderer}
|
|
@@ -36,9 +36,10 @@ type Props = {
|
|
|
36
36
|
component_type: string;
|
|
37
37
|
};
|
|
38
38
|
selected: boolean;
|
|
39
|
-
CellRenderer: React.
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
CellRenderer: React.ComponentType<{
|
|
40
|
+
item: any;
|
|
41
|
+
state: string;
|
|
42
|
+
}> & { hasFocusableInside: (item: any) => boolean };
|
|
42
43
|
preferredFocus: boolean;
|
|
43
44
|
navigator: {
|
|
44
45
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -53,6 +53,7 @@ export function ActionButton(props: Props) {
|
|
|
53
53
|
const { item, action, asset, flavour = "flavour_1", cellUUID } = props;
|
|
54
54
|
const actionContext = useActions(action?.identifier);
|
|
55
55
|
|
|
56
|
+
// TODO: add subscription API for action availability
|
|
56
57
|
const actionDisabled =
|
|
57
58
|
typeof actionContext?.isActionAvailable === "function" &&
|
|
58
59
|
!actionContext.isActionAvailable(item);
|
|
@@ -68,7 +69,7 @@ export function ActionButton(props: Props) {
|
|
|
68
69
|
if (actionDisabled || !actionContext) return;
|
|
69
70
|
|
|
70
71
|
setActionState(actionContext.initialEntryState(item));
|
|
71
|
-
}, [actionDisabled, item?.id]);
|
|
72
|
+
}, [actionDisabled, item?.id, actionContext]);
|
|
72
73
|
|
|
73
74
|
const onPress = useCallback(() => {
|
|
74
75
|
actionContext.invokeAction(item, {
|
|
@@ -117,9 +117,6 @@ export const BorderContainerView = (props: Props) => {
|
|
|
117
117
|
children,
|
|
118
118
|
} = props;
|
|
119
119
|
|
|
120
|
-
const borderStyleForMissingBorder =
|
|
121
|
-
style?.borderWidth === 0 || !style?.borderColor ? { borderRadius: 0 } : {};
|
|
122
|
-
|
|
123
120
|
const padding =
|
|
124
121
|
borderPosition === "outside"
|
|
125
122
|
? {
|
|
@@ -131,10 +128,7 @@ export const BorderContainerView = (props: Props) => {
|
|
|
131
128
|
: {};
|
|
132
129
|
|
|
133
130
|
return (
|
|
134
|
-
<View
|
|
135
|
-
{...props}
|
|
136
|
-
style={[style, styles.container, borderStyleForMissingBorder]}
|
|
137
|
-
>
|
|
131
|
+
<View {...props} style={[style, styles.container]}>
|
|
138
132
|
<Border style={style} padding={padding} borderPosition={borderPosition} />
|
|
139
133
|
{children}
|
|
140
134
|
</View>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ImageStyle } from "react-native";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getImageContainerMarginStyles,
|
|
5
|
+
ifElseFocusedSelected,
|
|
6
|
+
} from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
7
|
+
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
8
|
+
|
|
9
|
+
export const ImageBorderContainer = ({
|
|
10
|
+
value,
|
|
11
|
+
state,
|
|
12
|
+
imageStyles,
|
|
13
|
+
}: {
|
|
14
|
+
value: (key: string) => string;
|
|
15
|
+
state: CellState;
|
|
16
|
+
imageStyles: ImageStyle;
|
|
17
|
+
}) => {
|
|
18
|
+
return {
|
|
19
|
+
type: "BorderContainerView",
|
|
20
|
+
style: {
|
|
21
|
+
...getImageContainerMarginStyles({ value }),
|
|
22
|
+
position: "absolute",
|
|
23
|
+
top: 0,
|
|
24
|
+
zIndex: 1,
|
|
25
|
+
borderWidth: value("image_border_size"),
|
|
26
|
+
borderColor: ifElseFocusedSelected(
|
|
27
|
+
state,
|
|
28
|
+
value("image_focused_border_color"),
|
|
29
|
+
value("image_selected_border_color"),
|
|
30
|
+
value("image_focused_selected_border_color"),
|
|
31
|
+
value("image_border_color")
|
|
32
|
+
),
|
|
33
|
+
borderRadius: toNumberWithDefaultZero(value("image_corner_radius")),
|
|
34
|
+
},
|
|
35
|
+
additionalProps: {
|
|
36
|
+
borderPosition: value("image_border_position"),
|
|
37
|
+
borderPaddingTop: toNumberWithDefaultZero(
|
|
38
|
+
value("image_border_padding_top")
|
|
39
|
+
),
|
|
40
|
+
borderPaddingRight: toNumberWithDefaultZero(
|
|
41
|
+
value("image_border_padding_right")
|
|
42
|
+
),
|
|
43
|
+
borderPaddingBottom: toNumberWithDefaultZero(
|
|
44
|
+
value("image_border_padding_bottom")
|
|
45
|
+
),
|
|
46
|
+
borderPaddingLeft: toNumberWithDefaultZero(
|
|
47
|
+
value("image_border_padding_left")
|
|
48
|
+
),
|
|
49
|
+
},
|
|
50
|
+
elements: [
|
|
51
|
+
{
|
|
52
|
+
type: "View",
|
|
53
|
+
style: imageStyles,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
};
|
|
@@ -15,6 +15,7 @@ import { BorderContainerView } from "./BorderContainerView";
|
|
|
15
15
|
import { CellBadge } from "./CellBadge";
|
|
16
16
|
import { TvActionButtons } from "./tv/TvActionButtons";
|
|
17
17
|
import { ButtonContainerView } from "./tv/ButtonContainerView";
|
|
18
|
+
import { ImageBorderContainer } from "./ImageBorderContainer";
|
|
18
19
|
|
|
19
20
|
export const defaultComponents = {
|
|
20
21
|
View,
|
|
@@ -28,6 +29,7 @@ export const defaultComponents = {
|
|
|
28
29
|
ProgressBar,
|
|
29
30
|
Toggle,
|
|
30
31
|
LiveImage,
|
|
32
|
+
ImageBorderContainer,
|
|
31
33
|
BorderContainerView,
|
|
32
34
|
DynamicBadge,
|
|
33
35
|
SecondaryImage,
|
|
@@ -37,14 +37,28 @@ function retrieveData(entry, func, args) {
|
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
39
|
export function configInflater(
|
|
40
|
-
entry,
|
|
41
|
-
{
|
|
40
|
+
entry: any,
|
|
41
|
+
{
|
|
42
|
+
type,
|
|
43
|
+
style,
|
|
44
|
+
additionalProps = {},
|
|
45
|
+
data = [],
|
|
46
|
+
elements,
|
|
47
|
+
}: {
|
|
48
|
+
type: any;
|
|
49
|
+
style: any;
|
|
50
|
+
additionalProps?: Record<string, any>;
|
|
51
|
+
data?: Array<{ propName: string; func: Function; args: any[] }>;
|
|
52
|
+
elements?: any[];
|
|
53
|
+
}
|
|
42
54
|
) {
|
|
43
|
-
const props =
|
|
44
|
-
(acc, curr) =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const props = data.reduce(
|
|
56
|
+
(acc, curr) => {
|
|
57
|
+
acc[curr.propName] = retrieveData(entry, curr.func, curr.args);
|
|
58
|
+
|
|
59
|
+
return acc;
|
|
60
|
+
},
|
|
61
|
+
{ ...additionalProps }
|
|
48
62
|
);
|
|
49
63
|
|
|
50
64
|
let adjustedElements;
|
|
@@ -52,6 +52,8 @@ export function masterCellBuilder({
|
|
|
52
52
|
const { View } = componentsMap;
|
|
53
53
|
const elementsBuilder = dataAdapter(cellConfiguration);
|
|
54
54
|
|
|
55
|
+
// This is very expensive operation
|
|
56
|
+
// Keep calls to minimum
|
|
55
57
|
const hasFocusableInside = hasFocusableInsideBuilder(elementsBuilder);
|
|
56
58
|
|
|
57
59
|
/**
|
|
@@ -74,8 +76,8 @@ export function masterCellBuilder({
|
|
|
74
76
|
const selectedState = screen?.selectedEntry;
|
|
75
77
|
|
|
76
78
|
const entryIsSelected = React.useMemo(
|
|
77
|
-
() => selectedState?.id === item?.id,
|
|
78
|
-
[selectedState?.id]
|
|
79
|
+
() => !!(selectedState?.id && selectedState?.id === item?.id),
|
|
80
|
+
[selectedState?.id, item?.id]
|
|
79
81
|
);
|
|
80
82
|
|
|
81
83
|
const elements = React.useMemo(
|
|
@@ -84,7 +86,7 @@ export function masterCellBuilder({
|
|
|
84
86
|
entry: item,
|
|
85
87
|
state: getEntryState(state, entryIsSelected),
|
|
86
88
|
}),
|
|
87
|
-
[state, item, entryIsSelected]
|
|
89
|
+
[state, item?.id, entryIsSelected] // Assuming that item won't mutate
|
|
88
90
|
);
|
|
89
91
|
|
|
90
92
|
const wrapperRef = React.useRef(null);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { requireNativeComponent, View } from "react-native";
|
|
2
2
|
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
3
3
|
|
|
4
|
-
// @TODO define the types
|
|
5
4
|
export const FocusableGroupNative = isAppleTV()
|
|
6
|
-
? requireNativeComponent
|
|
5
|
+
? requireNativeComponent("FocusableGroupViewModule", null)
|
|
7
6
|
: View;
|
|
8
7
|
|
|
9
|
-
// @TODO define the types
|
|
10
8
|
export const FocusableItemNative = isAppleTV()
|
|
11
|
-
? requireNativeComponent
|
|
9
|
+
? requireNativeComponent("FocusableViewModule", null)
|
|
12
10
|
: View;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
import { useDispatch } from "react-redux";
|
|
2
|
+
import { path, prop } from "ramda";
|
|
4
3
|
import {
|
|
5
4
|
findPluginByType,
|
|
6
5
|
findPluginByIdentifier,
|
|
@@ -15,7 +14,6 @@ import { componentsLogger } from "../../Helpers/logger";
|
|
|
15
14
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
16
15
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
17
16
|
import { useScreenAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks";
|
|
18
|
-
import { setAppStateHasFinishedTransitioning } from "@applicaster/zapp-react-native-redux/appState";
|
|
19
17
|
|
|
20
18
|
const logger = componentsLogger.addSubsystem("ScreenResolver");
|
|
21
19
|
|
|
@@ -54,11 +52,8 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
54
52
|
|
|
55
53
|
const [, setScreenContext] = ZappPipesScreenContext.useZappPipesContext();
|
|
56
54
|
|
|
57
|
-
const dispatch = useDispatch();
|
|
58
|
-
|
|
59
55
|
React.useEffect(() => {
|
|
60
56
|
setScreenContext(rivers[screenId]);
|
|
61
|
-
dispatch(setAppStateHasFinishedTransitioning());
|
|
62
57
|
}, [screenId]);
|
|
63
58
|
|
|
64
59
|
const ScreenPlugin =
|
|
@@ -100,14 +95,14 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
100
95
|
}
|
|
101
96
|
|
|
102
97
|
const ScreenComponent =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
path(["module", "Component"], ScreenPlugin) ||
|
|
99
|
+
prop("module", ScreenPlugin) ||
|
|
100
|
+
prop("Component", ScreenPlugin) ||
|
|
106
101
|
ScreenPlugin;
|
|
107
102
|
|
|
108
103
|
const configuration =
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
prop("configuration", ScreenPlugin) ||
|
|
105
|
+
prop("__plugin_configuration", ScreenComponent);
|
|
111
106
|
|
|
112
107
|
if (ScreenComponent) {
|
|
113
108
|
return (
|
|
@@ -166,21 +166,23 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
166
166
|
|
|
167
167
|
transitionWithoutAnimation(resetState) {
|
|
168
168
|
const { scenes } = this.state;
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
169
|
+
const newScene = prepareScene(this.props.children);
|
|
170
|
+
const isLastSceneHook = scenes[scenes.length - 1].key.startsWith("/hook");
|
|
171
|
+
|
|
172
|
+
let newState;
|
|
173
|
+
|
|
174
|
+
if (resetState) {
|
|
175
|
+
newState = {
|
|
176
|
+
scenes: [newScene],
|
|
177
|
+
to: { index: 0 },
|
|
178
|
+
};
|
|
179
|
+
} else if (isLastSceneHook || scenes.length === 1) {
|
|
180
|
+
newState = { scenes: R.update(scenes.length - 1, newScene, scenes) };
|
|
181
|
+
} else {
|
|
182
|
+
newState = {
|
|
183
|
+
scenes: R.compose(R.tail, R.append(newScene))(scenes),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
184
186
|
|
|
185
187
|
this.setState(newState);
|
|
186
188
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
5
|
-
import { AppState, AppStateStatus } from "react-native";
|
|
5
|
+
import { AppState, AppStateStatus, View } from "react-native";
|
|
6
6
|
import { TrackedView } from "../TrackedView";
|
|
7
7
|
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
|
|
8
8
|
|
|
@@ -25,8 +25,9 @@ import { PlayerRole } from "@applicaster/zapp-react-native-utils/appUtils/player
|
|
|
25
25
|
import { getAutoplaySettings } from "./utils";
|
|
26
26
|
import { isString } from "@applicaster/zapp-react-native-utils/stringUtils";
|
|
27
27
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
28
|
+
import { useEffect } from "react";
|
|
28
29
|
|
|
29
|
-
const { log_error } = loggerLiveImageComponent;
|
|
30
|
+
const { log_error, log_debug } = loggerLiveImageComponent;
|
|
30
31
|
|
|
31
32
|
const isMeasurement = (item: ZappEntry) =>
|
|
32
33
|
isString(item.id) && item.id.startsWith("pre-measurement-");
|
|
@@ -56,6 +57,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
56
57
|
);
|
|
57
58
|
|
|
58
59
|
const ref = React.useRef(null);
|
|
60
|
+
const trackViewRef = React.useRef(null);
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* Debounced setMode function.
|
|
@@ -86,6 +88,30 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
86
88
|
[mode]
|
|
87
89
|
);
|
|
88
90
|
|
|
91
|
+
const entryToViewIdMapping = React.useRef({});
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
const nativeTag = trackViewRef.current?._nativeTag?.toString();
|
|
95
|
+
|
|
96
|
+
if (!nativeTag) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const prevValue = entryToViewIdMapping.current[nativeTag];
|
|
101
|
+
|
|
102
|
+
if (prevValue && prevValue.itemId !== item.id) {
|
|
103
|
+
if (mode === LiveImageType.Video) {
|
|
104
|
+
log_debug(
|
|
105
|
+
"Entry to view association changed, stopping current live image"
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
setMode(LiveImageType.Image);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
entryToViewIdMapping.current[nativeTag] = { itemId: item.id };
|
|
113
|
+
}, [trackViewRef.current, item.id, mode]);
|
|
114
|
+
|
|
89
115
|
const { screenConfig, playerPluginId } = props;
|
|
90
116
|
|
|
91
117
|
const liveImageItem: LiveImage = React.useMemo(() => {
|
|
@@ -295,28 +321,30 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
295
321
|
testId={`tracked-view-${playerId}-${item.title}`}
|
|
296
322
|
onPositionUpdated={onPositionUpdated}
|
|
297
323
|
>
|
|
298
|
-
{
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
324
|
+
<View ref={trackViewRef}>
|
|
325
|
+
{isVideoMode && (
|
|
326
|
+
<Player
|
|
327
|
+
autoplay={false}
|
|
328
|
+
ref={_assignRoot}
|
|
329
|
+
entry={item} // Must be passed first in list
|
|
330
|
+
style={videoStyles}
|
|
331
|
+
playerId={playerId}
|
|
332
|
+
muted={muted}
|
|
333
|
+
listener={controller?.getListener()}
|
|
334
|
+
resizeMode={"cover"}
|
|
335
|
+
{...platformSpecificProps}
|
|
336
|
+
/>
|
|
337
|
+
)}
|
|
338
|
+
{
|
|
339
|
+
<AnimatedInOut
|
|
340
|
+
visible={isBackgroundImageVisible}
|
|
341
|
+
animationConfig={overlayFadeIn}
|
|
342
|
+
staticStyles={style}
|
|
343
|
+
>
|
|
344
|
+
<Image {...props} resizeMode="cover" style={style} applyMaxSize />
|
|
345
|
+
</AnimatedInOut>
|
|
346
|
+
}
|
|
347
|
+
</View>
|
|
320
348
|
</TrackedView>
|
|
321
349
|
);
|
|
322
350
|
};
|
|
@@ -5,33 +5,35 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
|
|
|
5
5
|
onPositionUpdated={[Function]}
|
|
6
6
|
testId="tracked-view-player1-Test"
|
|
7
7
|
>
|
|
8
|
-
<View
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"opacity": 1,
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
>
|
|
16
|
-
<Image
|
|
17
|
-
applyMaxSize={true}
|
|
18
|
-
audioMutedByDefault={false}
|
|
19
|
-
imageKey="image1"
|
|
20
|
-
item={
|
|
8
|
+
<View>
|
|
9
|
+
<View
|
|
10
|
+
collapsable={false}
|
|
11
|
+
style={
|
|
21
12
|
Object {
|
|
22
|
-
"
|
|
23
|
-
"title": "Test",
|
|
24
|
-
"type": Object {
|
|
25
|
-
"value": "",
|
|
26
|
-
},
|
|
13
|
+
"opacity": 1,
|
|
27
14
|
}
|
|
28
15
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
>
|
|
17
|
+
<Image
|
|
18
|
+
applyMaxSize={true}
|
|
19
|
+
audioMutedByDefault={false}
|
|
20
|
+
imageKey="image1"
|
|
21
|
+
item={
|
|
22
|
+
Object {
|
|
23
|
+
"id": "1",
|
|
24
|
+
"title": "Test",
|
|
25
|
+
"type": Object {
|
|
26
|
+
"value": "",
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
onError={[Function]}
|
|
31
|
+
playerId="player1"
|
|
32
|
+
resizeMode="cover"
|
|
33
|
+
screenConfig={Object {}}
|
|
34
|
+
style={Object {}}
|
|
35
|
+
/>
|
|
36
|
+
</View>
|
|
35
37
|
</View>
|
|
36
38
|
</TrackedView>
|
|
37
39
|
`;
|
|
@@ -349,7 +349,12 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
|
349
349
|
};
|
|
350
350
|
|
|
351
351
|
export const AnimatedScrollModal = ({ children }: Props) => {
|
|
352
|
-
const
|
|
352
|
+
const {
|
|
353
|
+
videoModalState: { visible },
|
|
354
|
+
} = useNavigation();
|
|
355
|
+
|
|
356
|
+
const Component =
|
|
357
|
+
!isTV() && visible ? AnimatedScrollModalComponent : React.Fragment;
|
|
353
358
|
|
|
354
359
|
return <Component>{children}</Component>;
|
|
355
360
|
};
|
|
@@ -155,7 +155,11 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
|
|
|
155
155
|
};
|
|
156
156
|
|
|
157
157
|
export const AnimatedVideoPlayerComponent = ({ children }: Props) => {
|
|
158
|
-
const
|
|
158
|
+
const {
|
|
159
|
+
videoModalState: { visible },
|
|
160
|
+
} = useNavigation();
|
|
161
|
+
|
|
162
|
+
const Component = !isTV() && visible ? AnimatedVideoPlayer : React.Fragment;
|
|
159
163
|
|
|
160
164
|
return <Component>{children}</Component>;
|
|
161
165
|
};
|
|
@@ -72,12 +72,34 @@ exports[`PlayerWrapper renders inline 1`] = `
|
|
|
72
72
|
testID="test-player-container"
|
|
73
73
|
/>
|
|
74
74
|
<View
|
|
75
|
+
animationType="componentFade"
|
|
75
76
|
style={
|
|
76
77
|
Object {
|
|
77
78
|
"flex": 1,
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
>
|
|
82
|
+
<View
|
|
83
|
+
configuration={
|
|
84
|
+
Object {
|
|
85
|
+
"tablet_landscape_player_container_background_color": "red",
|
|
86
|
+
"tablet_landscape_sidebar_width": "35%",
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
entry={
|
|
90
|
+
Object {
|
|
91
|
+
"id": "test",
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
isTabletLandscape={false}
|
|
95
|
+
style={
|
|
96
|
+
Object {
|
|
97
|
+
"flex": 1,
|
|
98
|
+
"paddingTop": 20,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/>
|
|
102
|
+
</View>
|
|
81
103
|
</View>
|
|
82
104
|
</RNCSafeAreaView>
|
|
83
105
|
</RNCSafeAreaProvider>
|
|
@@ -158,6 +180,7 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
|
|
|
158
180
|
style={
|
|
159
181
|
Object {
|
|
160
182
|
"flex": 1,
|
|
183
|
+
"paddingTop": 20,
|
|
161
184
|
}
|
|
162
185
|
}
|
|
163
186
|
/>
|
|
@@ -254,12 +277,34 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
|
|
|
254
277
|
/>
|
|
255
278
|
</View>
|
|
256
279
|
<View
|
|
280
|
+
animationType="componentFade"
|
|
257
281
|
style={
|
|
258
282
|
Object {
|
|
259
283
|
"flex": 1,
|
|
260
284
|
}
|
|
261
285
|
}
|
|
262
|
-
|
|
286
|
+
>
|
|
287
|
+
<View
|
|
288
|
+
configuration={
|
|
289
|
+
Object {
|
|
290
|
+
"tablet_landscape_player_container_background_color": "red",
|
|
291
|
+
"tablet_landscape_sidebar_width": "35%",
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
entry={
|
|
295
|
+
Object {
|
|
296
|
+
"id": "test",
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
isTabletLandscape={true}
|
|
300
|
+
style={
|
|
301
|
+
Object {
|
|
302
|
+
"flex": 1,
|
|
303
|
+
"paddingTop": 20,
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/>
|
|
307
|
+
</View>
|
|
263
308
|
</View>
|
|
264
309
|
</RNCSafeAreaView>
|
|
265
310
|
</RNCSafeAreaProvider>
|
|
@@ -340,6 +385,7 @@ exports[`PlayerWrapper renders properly 1`] = `
|
|
|
340
385
|
style={
|
|
341
386
|
Object {
|
|
342
387
|
"flex": 1,
|
|
388
|
+
"paddingTop": 20,
|
|
343
389
|
}
|
|
344
390
|
}
|
|
345
391
|
/>
|
package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap
CHANGED
|
@@ -16,9 +16,9 @@ exports[`DefaultCellRenderer returns a react component and it renders correctly
|
|
|
16
16
|
store={null}
|
|
17
17
|
style={
|
|
18
18
|
Object {
|
|
19
|
-
"backgroundColor": "
|
|
19
|
+
"backgroundColor": "transparent",
|
|
20
20
|
"margin": 12,
|
|
21
|
-
"opacity":
|
|
21
|
+
"opacity": 1,
|
|
22
22
|
"width": 169,
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -105,7 +105,7 @@ exports[`DefaultCellRenderer returns a react component for LG TVs 1`] = `
|
|
|
105
105
|
store={null}
|
|
106
106
|
style={
|
|
107
107
|
Object {
|
|
108
|
-
"backgroundColor": "rgba(
|
|
108
|
+
"backgroundColor": "rgba(47,47,47,1.0)",
|
|
109
109
|
"borderRadius": 4,
|
|
110
110
|
"flex": 1,
|
|
111
111
|
"overflow": "hidden",
|
|
@@ -238,7 +238,7 @@ exports[`DefaultCellRenderer returns a react component for Samsung TVs 1`] = `
|
|
|
238
238
|
store={null}
|
|
239
239
|
style={
|
|
240
240
|
Object {
|
|
241
|
-
"backgroundColor": "rgba(
|
|
241
|
+
"backgroundColor": "rgba(47,47,47,1.0)",
|
|
242
242
|
"borderRadius": 4,
|
|
243
243
|
"flex": 1,
|
|
244
244
|
"overflow": "hidden",
|
|
@@ -5,18 +5,18 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
5
5
|
|
|
6
6
|
type ComponentProps = {
|
|
7
7
|
component: {
|
|
8
|
-
id: string
|
|
9
|
-
rules: { item_limit: number
|
|
10
|
-
component_type: string
|
|
8
|
+
id: string,
|
|
9
|
+
rules: { item_limit: number, component_cells_selectable: boolean },
|
|
10
|
+
component_type: string,
|
|
11
11
|
styles: {
|
|
12
|
-
cell_style: string
|
|
13
|
-
header: { visible: boolean }
|
|
14
|
-
component_cells_selectable: boolean
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
zappPipesData: { url: string
|
|
18
|
-
selected: boolean
|
|
19
|
-
assets: { menu_button: string }
|
|
12
|
+
cell_style: string,
|
|
13
|
+
header: { visible: boolean },
|
|
14
|
+
component_cells_selectable: boolean,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
zappPipesData: { url: string, data: { title: string } },
|
|
18
|
+
selected: boolean,
|
|
19
|
+
assets: { menu_button: string },
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
function withAnalytics(Component) {
|
package/README.md
CHANGED
|
@@ -78,6 +78,17 @@ export default MyAwesomeComponent;
|
|
|
78
78
|
export { MyAwesomeComponent } from "./MyAwesomeComponent";
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
We provide flow types for component props - please use it to make sure your component will be compliant
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import * as React from "react";
|
|
85
|
+
import type { ZappComponentProps } from "../../flow-types"; // in the root of the project
|
|
86
|
+
|
|
87
|
+
export class MyComponent extends React.Component<ZappComponentProps> {
|
|
88
|
+
/* ... */
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
81
92
|
## Connecting my component to Zapp Pipes
|
|
82
93
|
|
|
83
94
|
Zapp App components rely on [Zapp-Pipes](https://github.com/applicaster/zapp-pipes) to load data.
|
|
@@ -89,9 +100,10 @@ In order to connect your component to ZappPipes, you simply need to use the `Zap
|
|
|
89
100
|
import * as React from "react";
|
|
90
101
|
import { View, Text } from "react-native";
|
|
91
102
|
import { zappPipesDataConnector } from "../ZappPipesDataConnector";
|
|
103
|
+
import type { ZappComponentProps } from "../../flow-types";
|
|
92
104
|
|
|
93
105
|
@zappPipesDataConnector
|
|
94
|
-
export class MyComponent extends React.Component {
|
|
106
|
+
export class MyComponent extends React.Component<ZappComponentProps> {
|
|
95
107
|
renderComponent = (data) => {
|
|
96
108
|
return (
|
|
97
109
|
<View>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.4155487673",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"redux-mock-store": "^1.5.3"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@applicaster/applicaster-types": "12.0.0-alpha.
|
|
38
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-alpha.
|
|
39
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-alpha.
|
|
40
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.
|
|
37
|
+
"@applicaster/applicaster-types": "12.0.0-alpha.4155487673",
|
|
38
|
+
"@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4155487673",
|
|
39
|
+
"@applicaster/zapp-react-native-redux": "12.0.0-alpha.4155487673",
|
|
40
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.4155487673",
|
|
41
41
|
"promise": "^8.3.0",
|
|
42
42
|
"react-router-native": "^5.1.2",
|
|
43
43
|
"url": "^0.11.0",
|