@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3977160850 → 12.0.0-alpha.4054240460
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 +16 -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 +19 -87
- package/Components/Layout/TV/index.tsx +12 -11
- package/Components/Layout/TV/index.web.tsx +33 -0
- package/Components/Layout/index.tsx +15 -11
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -109
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- 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 +35 -37
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/Navigator/StackNavigator.tsx +48 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +69 -31
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -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/Screen/TV/hooks/index.ts +3 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
- package/Components/Screen/TV/index.web.tsx +179 -0
- package/Components/Screen/__tests__/Screen.test.tsx +8 -1
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +14 -0
- package/Components/Screen/index.tsx +77 -29
- package/Components/ScreenResolver/index.tsx +3 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +21 -28
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +18 -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 +352 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +158 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +461 -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/PlayerDetails.tsx +3 -3
- package/Components/VideoModal/PlayerWrapper.tsx +77 -47
- package/Components/VideoModal/VideoModal.tsx +23 -40
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/utils.ts +8 -5
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- 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/ScreenDataContext/index.tsx +20 -0
- 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
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { join, path, merge } from "ramda";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
|
|
5
5
|
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
|
|
@@ -11,6 +11,10 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
11
11
|
|
|
12
12
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
13
|
import { BaseFocusable } from "../BaseFocusable";
|
|
14
|
+
import {
|
|
15
|
+
isVizioPlatform,
|
|
16
|
+
TTSManager,
|
|
17
|
+
} from "@applicaster/zapp-react-native-utils/appUtils/platform/platformUtils";
|
|
14
18
|
|
|
15
19
|
type Props = {
|
|
16
20
|
item: {
|
|
@@ -105,8 +109,8 @@ export class CellComponent extends React.Component<Props> {
|
|
|
105
109
|
onPress(item, index);
|
|
106
110
|
} else {
|
|
107
111
|
const { item, navigator, component, appData } = this.props;
|
|
108
|
-
const itemTargetScreen =
|
|
109
|
-
const componentTargetScreen =
|
|
112
|
+
const itemTargetScreen = path(["screen_type"], item);
|
|
113
|
+
const componentTargetScreen = path(["data", "target"], component);
|
|
110
114
|
const itemType = getItemType(item, appData?.layoutVersion);
|
|
111
115
|
|
|
112
116
|
sendSelectCellEvent(item, component, item.title, index);
|
|
@@ -116,7 +120,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
116
120
|
componentTargetScreen &&
|
|
117
121
|
!itemTargetScreen
|
|
118
122
|
) {
|
|
119
|
-
navigator.push(
|
|
123
|
+
navigator.push(merge(item, { screen_type: componentTargetScreen }));
|
|
120
124
|
|
|
121
125
|
return;
|
|
122
126
|
}
|
|
@@ -139,6 +143,11 @@ export class CellComponent extends React.Component<Props> {
|
|
|
139
143
|
shouldScrollVertically?.(mouse, focusable, id, title)
|
|
140
144
|
) {
|
|
141
145
|
this.scrollVertically(focusable);
|
|
146
|
+
|
|
147
|
+
if (isVizioPlatform()) {
|
|
148
|
+
const ttsManager = TTSManager.getInstance();
|
|
149
|
+
ttsManager.readText(title);
|
|
150
|
+
}
|
|
142
151
|
}
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -202,12 +211,12 @@ export class CellComponent extends React.Component<Props> {
|
|
|
202
211
|
groupId,
|
|
203
212
|
isFocusable = true,
|
|
204
213
|
skipFocusManagerRegistration,
|
|
205
|
-
behavior
|
|
214
|
+
behavior,
|
|
206
215
|
} = this.props;
|
|
207
216
|
|
|
208
217
|
const { id } = item;
|
|
209
218
|
|
|
210
|
-
const focusableId =
|
|
219
|
+
const focusableId = join("-", [component?.id, id, index]);
|
|
211
220
|
|
|
212
221
|
const handleFocus = (focusable, mouse) => {
|
|
213
222
|
const focusFn = onFocus || noop;
|
|
@@ -263,7 +272,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
263
272
|
item,
|
|
264
273
|
focused: this.isCellFocused(focused),
|
|
265
274
|
scrollTo: this.scrollToIndex(event),
|
|
266
|
-
behavior
|
|
275
|
+
behavior,
|
|
267
276
|
}}
|
|
268
277
|
/>
|
|
269
278
|
);
|
|
@@ -6,12 +6,20 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
6
6
|
import { isAppleTV } from "../../Helpers/Platform";
|
|
7
7
|
import { useCellState } from "../MasterCell/utils";
|
|
8
8
|
|
|
9
|
-
const useCellFocusedState = (
|
|
9
|
+
const useCellFocusedState = (
|
|
10
|
+
skipFocusManagerRegistration: boolean,
|
|
11
|
+
groupId: string,
|
|
12
|
+
id: string
|
|
13
|
+
) => {
|
|
10
14
|
const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
|
|
11
15
|
|
|
12
16
|
React.useEffect(() => {
|
|
13
|
-
const isGroupItemFocused = () =>
|
|
14
|
-
|
|
17
|
+
const isGroupItemFocused = () => {
|
|
18
|
+
if (!skipFocusManagerRegistration) {
|
|
19
|
+
const isFocused = focusManager.isGroupItemFocused(groupId, id);
|
|
20
|
+
setCurrentCellFocused(isFocused);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
15
23
|
|
|
16
24
|
const handler = () => {
|
|
17
25
|
// tvOS hack for properly checking focus
|
|
@@ -29,24 +37,24 @@ const useCellFocusedState = (groupId: string, id: string) => {
|
|
|
29
37
|
return () => {
|
|
30
38
|
focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
|
|
31
39
|
};
|
|
32
|
-
}, [groupId]);
|
|
40
|
+
}, [groupId, skipFocusManagerRegistration]);
|
|
33
41
|
|
|
34
42
|
return currentCellFocused;
|
|
35
43
|
};
|
|
36
44
|
|
|
37
45
|
type Props = {
|
|
38
|
-
item: ZappEntry
|
|
39
|
-
CellRenderer: React.ComponentType<{ item: Object
|
|
40
|
-
id: string
|
|
41
|
-
groupId: string
|
|
42
|
-
onFocus: Function
|
|
43
|
-
index: number
|
|
44
|
-
scrollTo: Function
|
|
45
|
-
preferredFocus?: boolean
|
|
46
|
-
skipFocusManagerRegistration?: boolean
|
|
47
|
-
isFocusable?: boolean
|
|
48
|
-
behavior: Behavior
|
|
49
|
-
selected?: boolean
|
|
46
|
+
item: ZappEntry;
|
|
47
|
+
CellRenderer: React.ComponentType<{ item: Object; state: string }>;
|
|
48
|
+
id: string;
|
|
49
|
+
groupId: string;
|
|
50
|
+
onFocus: Function;
|
|
51
|
+
index: number;
|
|
52
|
+
scrollTo: Function;
|
|
53
|
+
preferredFocus?: boolean;
|
|
54
|
+
skipFocusManagerRegistration?: boolean;
|
|
55
|
+
isFocusable?: boolean;
|
|
56
|
+
behavior: Behavior;
|
|
57
|
+
selected?: boolean;
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
export function CellWithFocusable(props: Props) {
|
|
@@ -62,11 +70,22 @@ export function CellWithFocusable(props: Props) {
|
|
|
62
70
|
skipFocusManagerRegistration,
|
|
63
71
|
isFocusable,
|
|
64
72
|
behavior,
|
|
65
|
-
selected
|
|
73
|
+
selected,
|
|
66
74
|
} = props;
|
|
67
75
|
|
|
68
|
-
const isFocused = useCellFocusedState(
|
|
69
|
-
|
|
76
|
+
const isFocused = useCellFocusedState(
|
|
77
|
+
skipFocusManagerRegistration,
|
|
78
|
+
groupId,
|
|
79
|
+
id
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const state = useCellState({
|
|
83
|
+
id: item.id,
|
|
84
|
+
behavior,
|
|
85
|
+
focused: isFocused,
|
|
86
|
+
selected,
|
|
87
|
+
});
|
|
88
|
+
|
|
70
89
|
const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);
|
|
71
90
|
|
|
72
91
|
// for horizontal scrolling
|
|
@@ -249,7 +249,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
249
249
|
hasReceivedFocus,
|
|
250
250
|
groupId,
|
|
251
251
|
isFocusable,
|
|
252
|
-
behavior
|
|
252
|
+
behavior,
|
|
253
253
|
} = this.props;
|
|
254
254
|
|
|
255
255
|
const { id } = item;
|
|
@@ -310,7 +310,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
310
310
|
item,
|
|
311
311
|
focused: this.props.focused || selectedCell || focused,
|
|
312
312
|
scrollTo: this.scrollTo,
|
|
313
|
-
behavior
|
|
313
|
+
behavior,
|
|
314
314
|
}}
|
|
315
315
|
/>
|
|
316
316
|
);
|
|
@@ -3,7 +3,6 @@ import * as R from "ramda";
|
|
|
3
3
|
import {
|
|
4
4
|
View,
|
|
5
5
|
StyleSheet,
|
|
6
|
-
Image,
|
|
7
6
|
Text,
|
|
8
7
|
ViewStyle,
|
|
9
8
|
TextStyle,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
import { defaultAsset } from "./defaultAsset";
|
|
14
13
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
15
14
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
15
|
+
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
16
16
|
import { Button } from "./Button";
|
|
17
17
|
|
|
18
18
|
type ButtonProp = {
|
|
@@ -3,12 +3,12 @@ import { Platform } from "react-native";
|
|
|
3
3
|
import { useCellState } from "../MasterCell/utils";
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
|
-
index: number
|
|
7
|
-
item: ZappEntry
|
|
8
|
-
focused: boolean
|
|
9
|
-
scrollTo?: (index: number) => void
|
|
10
|
-
CellRenderer: React.ComponentType<{ item: Object
|
|
11
|
-
behavior: Behavior
|
|
6
|
+
index: number;
|
|
7
|
+
item: ZappEntry;
|
|
8
|
+
focused: boolean;
|
|
9
|
+
scrollTo?: (index: number) => void;
|
|
10
|
+
CellRenderer: React.ComponentType<{ item: Object; state: string }>;
|
|
11
|
+
behavior: Behavior;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const isAndroid = Platform.OS === "android";
|
|
@@ -20,7 +20,7 @@ export function FocusableCell(props: Props) {
|
|
|
20
20
|
CellRenderer,
|
|
21
21
|
focused,
|
|
22
22
|
scrollTo = null,
|
|
23
|
-
behavior
|
|
23
|
+
behavior,
|
|
24
24
|
} = props;
|
|
25
25
|
|
|
26
26
|
const state = useCellState({ id: item.id, behavior, focused });
|
|
@@ -50,7 +50,11 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
expect(transformed_preset).toBeDefined();
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
expect(transformed_preset.id).toEqual(
|
|
55
|
+
`${mockComp.id}-${mockPreset.feed_url}-0`
|
|
56
|
+
); // id was transformed
|
|
57
|
+
|
|
54
58
|
expect(transformed_preset.data.source).toEqual(mockPreset.feed_url); // source was replaced with preset feed_url.
|
|
55
59
|
});
|
|
56
60
|
});
|
|
@@ -117,7 +121,10 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
117
121
|
|
|
118
122
|
expect(Array.isArray(result)).toBe(true);
|
|
119
123
|
expect(result).toHaveLength(2);
|
|
120
|
-
|
|
124
|
+
|
|
125
|
+
expect(result[0].id).toEqual(
|
|
126
|
+
`${mockSmartComp.id}-${mockFeeds.preset_source.data.entry[0].feed_url}-0`
|
|
127
|
+
);
|
|
121
128
|
|
|
122
129
|
expect(result[0].data.source).toEqual(
|
|
123
130
|
mockFeeds.preset_source.data.entry[0].feed_url
|
|
@@ -287,7 +294,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
287
294
|
mockComponents[0],
|
|
288
295
|
{
|
|
289
296
|
...mockLayoutPresets.preset_one,
|
|
290
|
-
id: mockComponents[1].id
|
|
297
|
+
id: `${mockComponents[1].id}-${mockPresetEntry[0].feed_url}-1`,
|
|
291
298
|
data: { source: mockPresetEntry[0].feed_url },
|
|
292
299
|
},
|
|
293
300
|
];
|
|
@@ -344,12 +351,12 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
344
351
|
const mockTransformedComponents = [
|
|
345
352
|
{
|
|
346
353
|
...mockLayoutPresets.preset_one,
|
|
347
|
-
id: mockComponents[0].id
|
|
354
|
+
id: `${mockComponents[0].id}-${mockPresetEntry1[0].feed_url}-0`,
|
|
348
355
|
data: { source: mockPresetEntry1[0].feed_url },
|
|
349
356
|
},
|
|
350
357
|
{
|
|
351
358
|
...mockLayoutPresets.preset_one,
|
|
352
|
-
id: mockComponents[1].id
|
|
359
|
+
id: `${mockComponents[1].id}-${mockPresetEntry2[0].feed_url}-1`,
|
|
353
360
|
data: { source: mockPresetEntry2[0].feed_url },
|
|
354
361
|
},
|
|
355
362
|
];
|
|
@@ -412,7 +419,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
412
419
|
const mockTransformedComponents = mockPresetEntry.map((preset, i) => {
|
|
413
420
|
return {
|
|
414
421
|
...mockLayoutPresets[preset.preset_name],
|
|
415
|
-
id: mockComponents[0].id
|
|
422
|
+
id: `${mockComponents[0].id}-${preset.feed_url}-${i}`,
|
|
416
423
|
data: { source: preset.feed_url },
|
|
417
424
|
};
|
|
418
425
|
});
|
|
@@ -41,7 +41,7 @@ export const getTransformedPreset = (
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const updatedPresetComponent = produce(presetComponent, (draft) => {
|
|
44
|
-
draft.id = `${componentId}
|
|
44
|
+
draft.id = `${componentId}-${preset?.feed_url}-${index}`;
|
|
45
45
|
draft.data.source = preset?.feed_url;
|
|
46
46
|
|
|
47
47
|
if (draft.ui_components) {
|
|
@@ -19,6 +19,7 @@ type Props = {
|
|
|
19
19
|
modalHeight?: number;
|
|
20
20
|
modalWidth?: number;
|
|
21
21
|
mode: VideoModalMode;
|
|
22
|
+
groupId?: string;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const YOUTUBE_PLUGIN_ID = "youtube-player-qb";
|
|
@@ -93,6 +94,7 @@ export function HandlePlayable({
|
|
|
93
94
|
modalHeight,
|
|
94
95
|
modalWidth,
|
|
95
96
|
mode,
|
|
97
|
+
groupId,
|
|
96
98
|
}: Props): React.ReactElement | null {
|
|
97
99
|
const state = usePickFromState();
|
|
98
100
|
|
|
@@ -167,6 +169,7 @@ export function HandlePlayable({
|
|
|
167
169
|
isModal={isModal}
|
|
168
170
|
mode={mode}
|
|
169
171
|
disableCastAction={playerModuleProperties?.disableCastAction}
|
|
172
|
+
groupId={groupId}
|
|
170
173
|
/>
|
|
171
174
|
);
|
|
172
175
|
}
|
|
@@ -3,32 +3,10 @@ import FastImage, {
|
|
|
3
3
|
FastImageProps,
|
|
4
4
|
} from "@applicaster/react-native-fast-image";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const source = React.useMemo(() => {
|
|
8
|
-
if (typeof props.source === "number") {
|
|
9
|
-
return props.source;
|
|
10
|
-
}
|
|
6
|
+
import { useImageSource } from "./utils";
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
headers: props.source.headers,
|
|
15
|
-
priority: props.source.priority,
|
|
16
|
-
cache: props.source.cache,
|
|
17
|
-
maxWidth: props.source.maxWidth,
|
|
18
|
-
maxHeight: props.source.maxHeight,
|
|
19
|
-
};
|
|
20
|
-
}, [
|
|
21
|
-
...(typeof props.source === "object"
|
|
22
|
-
? [
|
|
23
|
-
props.source?.uri,
|
|
24
|
-
props.source?.priority,
|
|
25
|
-
props.source?.cache,
|
|
26
|
-
props.source?.headers,
|
|
27
|
-
props.source?.maxWidth,
|
|
28
|
-
props.source?.maxHeight,
|
|
29
|
-
]
|
|
30
|
-
: []),
|
|
31
|
-
]);
|
|
8
|
+
export const QBImage = (props: FastImageProps) => {
|
|
9
|
+
const source = useImageSource(props.source);
|
|
32
10
|
|
|
33
11
|
return <FastImage {...props} source={source} />;
|
|
34
12
|
};
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Image,
|
|
4
|
+
ImageBackground,
|
|
5
|
+
ImageProps,
|
|
6
|
+
ImageStyle,
|
|
7
|
+
StyleProp,
|
|
8
|
+
} from "react-native";
|
|
2
9
|
|
|
3
10
|
export interface Props extends ImageProps {
|
|
4
11
|
style?: StyleProp<ImageStyle> | undefined;
|
|
5
12
|
}
|
|
6
13
|
|
|
7
14
|
// TODO - React.FC<Props> QBImage should process incoming url and apply any transformations if needed
|
|
8
|
-
export const QBImage =
|
|
15
|
+
export const QBImage = ({
|
|
16
|
+
children,
|
|
17
|
+
...props
|
|
18
|
+
}: Props & { children?: React.ReactNode }) => {
|
|
19
|
+
if (children) {
|
|
20
|
+
return <ImageBackground {...props}>{children}</ImageBackground>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return <Image {...props} />;
|
|
24
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import FastImage, { Source } from "@applicaster/react-native-fast-image";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { ImageRequireSource } from "react-native";
|
|
4
|
+
|
|
5
|
+
function getSourceCache(cache: Source["cache"]) {
|
|
6
|
+
return cache || FastImage.cacheControl.web;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useImageSource = (source?: Source | ImageRequireSource) => {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
if (source) {
|
|
12
|
+
if (typeof source === "number") {
|
|
13
|
+
return source;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
uri: source.uri,
|
|
18
|
+
headers: source.headers,
|
|
19
|
+
priority: source.priority,
|
|
20
|
+
cache: getSourceCache(source?.cache),
|
|
21
|
+
maxWidth: source.maxWidth,
|
|
22
|
+
maxHeight: source.maxHeight,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return undefined;
|
|
27
|
+
}, [
|
|
28
|
+
...(typeof source === "object"
|
|
29
|
+
? [
|
|
30
|
+
source?.uri,
|
|
31
|
+
source?.priority,
|
|
32
|
+
source?.cache,
|
|
33
|
+
source?.headers,
|
|
34
|
+
source?.maxWidth,
|
|
35
|
+
source?.maxHeight,
|
|
36
|
+
]
|
|
37
|
+
: []),
|
|
38
|
+
]);
|
|
39
|
+
};
|
|
@@ -60,7 +60,7 @@ export function ScreenLayoutContextProvider(props: {
|
|
|
60
60
|
initialState
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
const
|
|
63
|
+
const screenLayoutValue = React.useMemo(
|
|
64
64
|
() => ({
|
|
65
65
|
...screenLayout,
|
|
66
66
|
setScreenLayout,
|
|
@@ -69,7 +69,7 @@ export function ScreenLayoutContextProvider(props: {
|
|
|
69
69
|
);
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
|
-
<ScreenLayoutContext.Provider value={
|
|
72
|
+
<ScreenLayoutContext.Provider value={screenLayoutValue}>
|
|
73
73
|
{props.children}
|
|
74
74
|
</ScreenLayoutContext.Provider>
|
|
75
75
|
);
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Layout TV renders 1`] = `
|
|
4
4
|
<View
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"height": 1080,
|
|
9
|
-
"width": 1920,
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
testID="layout-container"
|
|
5
|
+
excludeFromFocusSearching={true}
|
|
6
|
+
id="/river/A1234"
|
|
7
|
+
preferredFocus={true}
|
|
13
8
|
>
|
|
14
9
|
<View
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
Components={
|
|
11
|
+
Object {
|
|
12
|
+
"Background": [Function],
|
|
13
|
+
"NavBar": [Function],
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
route="/river/A1234"
|
|
17
17
|
/>
|
|
18
18
|
</View>
|
|
19
19
|
`;
|
|
@@ -1,91 +1,48 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { omit } from "ramda";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
import { render } from "@testing-library/react-native";
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
|
-
import { createStore } from "redux";
|
|
7
6
|
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
|
|
7
|
+
import configureStore from "redux-mock-store";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const withoutChildren = omit(["children"]);
|
|
10
10
|
|
|
11
|
-
jest.mock("
|
|
12
|
-
|
|
11
|
+
jest.mock("../../../Screen/TV/index.web", () => ({
|
|
12
|
+
Screen: View,
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
|
-
|
|
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
|
-
}));
|
|
28
|
-
|
|
29
|
-
const Layout = require("..").default;
|
|
30
|
-
|
|
31
|
-
const ResolvedMenuPlug = () => <View testID="resolved-menu-plug" />;
|
|
15
|
+
const Layout = require("../index.web").default;
|
|
32
16
|
|
|
33
|
-
const
|
|
34
|
-
{
|
|
35
|
-
module: ResolvedMenuPlug,
|
|
36
|
-
type: "menu",
|
|
37
|
-
name: "resolved-menu-plug",
|
|
38
|
-
},
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const bgImage = "http://applicaster.com";
|
|
42
|
-
const isNavBarVisible = true;
|
|
43
|
-
|
|
44
|
-
const store = createStore(() => ({
|
|
17
|
+
const mockStore = configureStore()({
|
|
45
18
|
appState: { appReady: true },
|
|
46
|
-
|
|
47
|
-
plugins,
|
|
48
|
-
}));
|
|
19
|
+
});
|
|
49
20
|
|
|
50
21
|
describe("Layout TV", () => {
|
|
51
|
-
const themes = {
|
|
52
|
-
myTheme: { screen_margin_top: 10, screen_margin_bottom: 10 },
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const selectedThemeId = "myTheme";
|
|
56
|
-
|
|
57
22
|
const navigator = {
|
|
58
|
-
activeRiver: {
|
|
59
|
-
navigations: [{ category: "menu", navigation_type: "menu" }],
|
|
60
|
-
},
|
|
61
|
-
canGoBack: () => false,
|
|
62
23
|
currentRoute: "/river/A1234",
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
24
|
+
mainStack: [
|
|
25
|
+
{
|
|
26
|
+
route: "/river/A1234",
|
|
27
|
+
state: "state",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
67
30
|
};
|
|
68
31
|
|
|
69
32
|
const wrapper = ({ children }) => (
|
|
70
|
-
<Provider store={
|
|
33
|
+
<Provider store={mockStore}>
|
|
71
34
|
<NavigationContext.Provider value={navigator}>
|
|
72
|
-
|
|
73
|
-
{children}
|
|
74
|
-
</ThemeContext.Provider>
|
|
35
|
+
{children}
|
|
75
36
|
</NavigationContext.Provider>
|
|
76
37
|
</Provider>
|
|
77
38
|
);
|
|
78
39
|
|
|
79
|
-
const Screen = (props) => (
|
|
80
|
-
<View testID="screen-component" {...R.omit(["children"])(props)} />
|
|
81
|
-
);
|
|
82
|
-
|
|
83
40
|
const NavBar = (props) => (
|
|
84
|
-
<View testID="nav-bar-component" {...
|
|
41
|
+
<View testID="nav-bar-component" {...withoutChildren(props)} />
|
|
85
42
|
);
|
|
86
43
|
|
|
87
44
|
const Background = (props: Record<any, any>) => (
|
|
88
|
-
<View testID="background-component" {...
|
|
45
|
+
<View testID="background-component" {...withoutChildren(props)}>
|
|
89
46
|
{props.children}
|
|
90
47
|
</View>
|
|
91
48
|
);
|
|
@@ -96,33 +53,8 @@ describe("Layout TV", () => {
|
|
|
96
53
|
};
|
|
97
54
|
|
|
98
55
|
it("renders", () => {
|
|
99
|
-
const { toJSON } = render(
|
|
100
|
-
<Layout Components={Components}>
|
|
101
|
-
<Screen />
|
|
102
|
-
</Layout>,
|
|
103
|
-
{ wrapper }
|
|
104
|
-
);
|
|
56
|
+
const { toJSON } = render(<Layout Components={Components} />, { wrapper });
|
|
105
57
|
|
|
106
58
|
expect(toJSON()).toMatchSnapshot();
|
|
107
59
|
});
|
|
108
|
-
|
|
109
|
-
describe("props passed to background component", () => {
|
|
110
|
-
it("passes correct props", () => {
|
|
111
|
-
const { getByTestId } = render(
|
|
112
|
-
<Layout
|
|
113
|
-
Components={Components}
|
|
114
|
-
ComponentsExtraProps={{
|
|
115
|
-
Background: { testProp: true },
|
|
116
|
-
}}
|
|
117
|
-
>
|
|
118
|
-
<Screen />
|
|
119
|
-
</Layout>,
|
|
120
|
-
{ wrapper }
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const bgComponent = getByTestId("background-component");
|
|
124
|
-
expect(bgComponent.props.backgroundImageUrl).toBe(bgImage);
|
|
125
|
-
expect(bgComponent.props.testProp).toBe(true);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
60
|
});
|