@applicaster/zapp-react-native-ui-components 13.0.0-alpha.5771418585 → 13.0.0-alpha.5790181722
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/AppContainer/__tests__/AppContainer.test.js +4 -6
- package/Components/AudioPlayer/AudioPlayer.tsx +7 -0
- package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +54 -111
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +36 -20
- package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
- package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
- package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
- package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
- package/Components/AudioPlayer/__tests__/title.test.js +3 -5
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/BaseFocusable/index.tsx +1 -2
- package/Components/Cell/Cell.tsx +4 -13
- package/Components/Cell/CellWithFocusable.tsx +22 -15
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/Cell/TvOSCellComponent.tsx +20 -22
- package/Components/Cell/index.js +3 -1
- package/Components/Cell/styles.ts +17 -0
- package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +46 -48
- package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
- package/Components/ComponentResolver/__tests__/componentResolver.test.js +16 -22
- package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
- package/Components/ErrorScreen/index.tsx +8 -0
- package/Components/Focusable/FocusableTvOS.tsx +5 -1
- package/Components/Focusable/index.android.tsx +10 -3
- package/Components/FocusableCell/index.tsx +1 -1
- package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
- package/Components/FocusableGroup/index.tsx +0 -3
- package/Components/FocusableList/index.tsx +26 -9
- package/Components/FocusableScrollView/index.tsx +43 -13
- package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
- package/Components/Layout/TV/NavBarContainer.tsx +19 -23
- package/Components/Layout/TV/ScreenContainer.tsx +8 -1
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +2 -1
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -2
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +3 -2
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
- package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
- package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +4 -12
- package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +0 -229
- package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
- package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
- package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
- package/Components/MasterCell/utils/index.ts +8 -134
- package/Components/ModalComponent/BottomSheetModalContent.tsx +45 -19
- package/Components/ModalComponent/Button/Item.tsx +6 -5
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +29 -42
- package/Components/ModalComponent/utils.ts +55 -7
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
- package/Components/OfflineHandler/utils/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +32 -6
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +3 -0
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +3 -3
- package/Components/River/TV/index.tsx +6 -1
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +20 -82
- package/Components/River/__tests__/river.test.js +75 -40
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -4
- package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
- package/Components/RouteManager/__tests__/testId.test.js +8 -6
- package/Components/Screen/TV/index.web.tsx +5 -6
- package/Components/Screen/hooks.ts +3 -6
- package/Components/ScreenResolver/__tests__/screenResolver.test.js +91 -70
- package/Components/TrackedView/index.tsx +1 -0
- package/Components/Transitioner/AnimationManager.js +15 -15
- package/Components/Transitioner/__tests__/Scene.test.js +25 -14
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -68
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
- package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +4 -0
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +36 -20
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +3 -3
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +38 -13
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +2 -2
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
- package/Components/VideoModal/ModalAnimation/const.ts +5 -0
- package/Components/VideoModal/ModalAnimation/index.ts +2 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +36 -0
- package/Components/VideoModal/PlayerDetails.tsx +8 -5
- package/Components/VideoModal/PlayerWrapper.tsx +26 -3
- package/Components/VideoModal/VideoModal.tsx +19 -4
- package/Components/VideoModal/utils.ts +3 -4
- package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
- package/Components/Viewport/__tests__/utils.test.js +5 -4
- package/Components/ZappUIComponent/Placeholder.tsx +3 -1
- package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
- package/Components/ZappUIComponent/index.tsx +4 -17
- package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
- package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
- package/Contexts/HeaderOffsetContext/index.tsx +4 -6
- package/Contexts/ScreenContext/index.tsx +3 -10
- package/Contexts/ScreenLayoutContext/index.tsx +5 -3
- package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
- package/Decorators/Navigator/index.tsx +1 -1
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +18 -24
- package/Decorators/RiverResolver/index.tsx +6 -8
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
- package/Decorators/ZappPipesDataConnector/index.tsx +4 -30
- package/package.json +7 -11
- package/tsconfig.json +2 -3
- package/.babelrc +0 -8
- package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
- package/Components/Cell/CellStyles/Hero/index.js +0 -111
- package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
- package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
- package/Components/Cell/CellStyles/colors.js +0 -40
- package/Components/Cell/CellStyles/index.js +0 -15
- package/Components/Cell/CellWithFocusable.ios.tsx +0 -126
- package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
- package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
- package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
- package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
- package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
- package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import validateColor from "validate-color";
|
|
4
4
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
6
6
|
|
|
7
7
|
import { masterCellLogger } from "../logger";
|
|
8
|
-
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
9
|
-
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
10
|
-
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
11
|
-
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
12
8
|
import { getCellState } from "../../Cell/utils";
|
|
13
9
|
import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
|
+
import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
|
|
14
11
|
|
|
15
12
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
16
13
|
if (R.isNil(element)) {
|
|
@@ -193,147 +190,24 @@ export const getFocusedButtonId = (focusable) => {
|
|
|
193
190
|
});
|
|
194
191
|
};
|
|
195
192
|
|
|
196
|
-
export const isSelected = (
|
|
197
|
-
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (behavior?.selection_source === "now_playing") {
|
|
202
|
-
const player = playerManager.getActivePlayer();
|
|
203
|
-
|
|
204
|
-
if (player?.entry?.id === id) {
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (behavior?.select_mode === "single") {
|
|
210
|
-
return behavior.current_selection === id;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (behavior?.select_mode === "multi") {
|
|
214
|
-
// TODO: Use generic resolver source
|
|
215
|
-
|
|
216
|
-
if (behavior.selection_source === "@{push/topics}") {
|
|
217
|
-
const tags = PushTopicManager.getInstance().getRegisteredTags();
|
|
218
|
-
|
|
219
|
-
return tags.includes(String(id));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (Array.isArray(behavior.current_selection)) {
|
|
223
|
-
return behavior.current_selection.includes(id);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const currentSelection = String(behavior.current_selection);
|
|
227
|
-
|
|
228
|
-
if (currentSelection?.startsWith("@{ctx/")) {
|
|
229
|
-
const keyWithoutCtx = currentSelection.substring(
|
|
230
|
-
"@{ctx/".length,
|
|
231
|
-
currentSelection.length - 1
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
const selectedItems =
|
|
235
|
-
StorageMultiSelectProvider.getProvider(
|
|
236
|
-
keyWithoutCtx
|
|
237
|
-
)?.getSelectedItems();
|
|
238
|
-
|
|
239
|
-
return selectedItems?.includes(String(id));
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return false;
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
247
|
-
const [lastUpdate, setLastUpdate] = React.useState(null);
|
|
248
|
-
|
|
249
|
-
const player = usePlayer();
|
|
250
|
-
|
|
251
|
-
const triggerUpdate = () => {
|
|
252
|
-
setLastUpdate(Date.now());
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
// TODO: Create generic RX to state update
|
|
256
|
-
useEffect(() => {
|
|
257
|
-
// TODO: Use generic resolver source
|
|
258
|
-
if (!behavior) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const currentSelection = String(behavior.current_selection);
|
|
263
|
-
|
|
264
|
-
if (currentSelection?.startsWith("@{ctx/")) {
|
|
265
|
-
const keyWithoutCtx = currentSelection.substring(
|
|
266
|
-
"@{ctx/".length,
|
|
267
|
-
currentSelection.length - 1
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
if (keyWithoutCtx) {
|
|
271
|
-
const subscription = StorageMultiSelectProvider.getProvider(
|
|
272
|
-
keyWithoutCtx
|
|
273
|
-
)
|
|
274
|
-
.getObservable()
|
|
275
|
-
.subscribe(() => {
|
|
276
|
-
triggerUpdate();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
return () => {
|
|
280
|
-
subscription.unsubscribe();
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}, [behavior]);
|
|
285
|
-
|
|
286
|
-
useEffect(() => {
|
|
287
|
-
if (!behavior) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (behavior?.selection_source === "@{push/topics}") {
|
|
292
|
-
const subscription = PushTopicManager.getInstance()
|
|
293
|
-
.getEntryObservable()
|
|
294
|
-
.subscribe(() => {
|
|
295
|
-
triggerUpdate();
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
return () => {
|
|
299
|
-
subscription.unsubscribe();
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
}, [behavior]);
|
|
303
|
-
|
|
304
|
-
useEffect(() => {
|
|
305
|
-
if (!behavior) {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (behavior?.selection_source === "now_playing" && player) {
|
|
310
|
-
const subscription = player.getEntryObservable().subscribe(() => {
|
|
311
|
-
triggerUpdate();
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
return () => {
|
|
315
|
-
subscription.unsubscribe();
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
}, [behavior, player]);
|
|
319
|
-
|
|
320
|
-
return lastUpdate;
|
|
193
|
+
export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
|
|
194
|
+
return isCellSelected(item, behavior);
|
|
321
195
|
};
|
|
322
196
|
|
|
323
197
|
export const useCellState = ({
|
|
324
|
-
|
|
198
|
+
item,
|
|
325
199
|
behavior,
|
|
326
200
|
focused,
|
|
327
201
|
}: {
|
|
328
|
-
|
|
202
|
+
item: ZappEntry;
|
|
329
203
|
behavior: Behavior;
|
|
330
204
|
focused: boolean;
|
|
331
205
|
}): CellState => {
|
|
332
206
|
const lastUpdate = useBehaviorUpdate(behavior);
|
|
333
207
|
|
|
334
208
|
const _isSelected = useMemo(
|
|
335
|
-
() => isSelected(
|
|
336
|
-
[behavior,
|
|
209
|
+
() => isSelected(item, behavior),
|
|
210
|
+
[behavior, item, lastUpdate]
|
|
337
211
|
);
|
|
338
212
|
|
|
339
213
|
return getCellState({ focused, selected: _isSelected });
|
|
@@ -10,13 +10,11 @@ import { Button } from "./Button";
|
|
|
10
10
|
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
11
|
import { ItemProps } from "./Button/Item";
|
|
12
12
|
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
13
|
-
import {
|
|
14
|
-
defaultItemIconProps,
|
|
15
|
-
defaultItemLabelProps,
|
|
16
|
-
defaultItemProps,
|
|
17
|
-
} from "./utils";
|
|
13
|
+
import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
|
|
18
14
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
19
15
|
|
|
16
|
+
import type { PluginConfiguration } from "./";
|
|
17
|
+
|
|
20
18
|
import { ModalHeader } from "./Header";
|
|
21
19
|
|
|
22
20
|
type ModalComponentProps = {
|
|
@@ -30,6 +28,20 @@ type ModalComponentProps = {
|
|
|
30
28
|
maxHeight?: number;
|
|
31
29
|
dismiss: () => void;
|
|
32
30
|
buttonComponent?: React.ComponentType;
|
|
31
|
+
iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
|
|
32
|
+
itemProps?:
|
|
33
|
+
| ItemProps
|
|
34
|
+
| ((theme: PluginConfiguration, width: number) => ItemProps);
|
|
35
|
+
labelProps?:
|
|
36
|
+
| ItemLabelProps
|
|
37
|
+
| ((theme: PluginConfiguration, width: number) => ItemLabelProps);
|
|
38
|
+
getSelectedItemIcon: (
|
|
39
|
+
theme: PluginConfiguration
|
|
40
|
+
) => ItemIconProps["asset"] | null;
|
|
41
|
+
getDefaultItemIcon: (
|
|
42
|
+
theme: PluginConfiguration
|
|
43
|
+
) => ItemIconProps["asset"] | null;
|
|
44
|
+
iconPlacement?: "left" | "right";
|
|
33
45
|
};
|
|
34
46
|
|
|
35
47
|
export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
@@ -43,14 +55,20 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
43
55
|
summary,
|
|
44
56
|
title,
|
|
45
57
|
buttonComponent: ButtonComponent = Button,
|
|
58
|
+
getSelectedItemIcon = (theme) =>
|
|
59
|
+
theme.modal_bottom_sheet_item_selected_icon,
|
|
60
|
+
getDefaultItemIcon = () => null,
|
|
61
|
+
iconPlacement,
|
|
46
62
|
} = props;
|
|
47
63
|
|
|
48
64
|
const [headerHeight, setHeaderHeight] = useState(0);
|
|
49
65
|
const route = useRef(currentRoute);
|
|
50
66
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
67
|
+
const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
|
|
68
|
+
const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
|
|
51
69
|
|
|
52
70
|
const maxContentHeight = maxHeight
|
|
53
|
-
? maxHeight - headerHeight -
|
|
71
|
+
? maxHeight - headerHeight - paddingTop - paddingBottom
|
|
54
72
|
: undefined;
|
|
55
73
|
|
|
56
74
|
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
@@ -64,26 +82,30 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
64
82
|
}, [currentRoute]);
|
|
65
83
|
|
|
66
84
|
const iconBaseProps = useMemo<ItemIconProps>(() => {
|
|
67
|
-
return
|
|
68
|
-
}, [theme]);
|
|
85
|
+
return getItemIconProps(theme, props.iconProps);
|
|
86
|
+
}, [theme, props.iconProps]);
|
|
69
87
|
|
|
70
88
|
const itemBaseProps = useMemo<ItemProps>(() => {
|
|
71
|
-
return
|
|
72
|
-
}, [theme, props.width]);
|
|
89
|
+
return getItemProps(theme, props.width, props.itemProps);
|
|
90
|
+
}, [theme, props.width, props.itemProps]);
|
|
73
91
|
|
|
74
92
|
const labelBaseProps = useMemo<ItemLabelProps>(() => {
|
|
75
|
-
return
|
|
76
|
-
}, [theme, props.width]);
|
|
93
|
+
return getItemLabelProps(theme, props.width, props.labelProps);
|
|
94
|
+
}, [theme, props.width, props.labelProps]);
|
|
77
95
|
|
|
78
|
-
const handlePress = (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
const handlePress = useCallback(
|
|
97
|
+
(item: any) => {
|
|
98
|
+
onPress(item);
|
|
99
|
+
dismiss();
|
|
100
|
+
},
|
|
101
|
+
[onPress, dismiss]
|
|
102
|
+
);
|
|
82
103
|
|
|
83
104
|
return (
|
|
84
105
|
<View
|
|
85
106
|
style={{
|
|
86
|
-
|
|
107
|
+
maxWidth: props.width,
|
|
108
|
+
paddingTop,
|
|
87
109
|
}}
|
|
88
110
|
>
|
|
89
111
|
<ModalHeader
|
|
@@ -98,8 +120,8 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
98
120
|
bounces={false}
|
|
99
121
|
style={{ maxHeight: maxContentHeight }}
|
|
100
122
|
contentContainerStyle={{
|
|
101
|
-
paddingBottom
|
|
102
|
-
paddingTop
|
|
123
|
+
paddingBottom,
|
|
124
|
+
paddingTop,
|
|
103
125
|
}}
|
|
104
126
|
>
|
|
105
127
|
{items.map((item, index) => (
|
|
@@ -110,9 +132,13 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
110
132
|
selectedItem={current_selection}
|
|
111
133
|
item={item}
|
|
112
134
|
onPress={handlePress}
|
|
135
|
+
label={theme[item?.label] ?? item?.label}
|
|
113
136
|
iconBaseProps={iconBaseProps}
|
|
114
137
|
itemBaseProps={itemBaseProps}
|
|
115
138
|
labelBaseProps={labelBaseProps}
|
|
139
|
+
selectedItemIcon={getSelectedItemIcon(theme)}
|
|
140
|
+
defaultItemIcon={getDefaultItemIcon(theme)}
|
|
141
|
+
iconPlacement={iconPlacement}
|
|
116
142
|
/>
|
|
117
143
|
))}
|
|
118
144
|
</ScrollView>
|
|
@@ -5,7 +5,7 @@ export type ItemProps = {
|
|
|
5
5
|
backgroundColor: string;
|
|
6
6
|
focusedBackgroundColor: string;
|
|
7
7
|
selectedBackgroundColor?: string;
|
|
8
|
-
|
|
8
|
+
focusedSelectedBackgroundColor?: string;
|
|
9
9
|
borderRadius: number;
|
|
10
10
|
marginBottom: number;
|
|
11
11
|
marginLeft: number;
|
|
@@ -15,6 +15,7 @@ export type ItemProps = {
|
|
|
15
15
|
paddingBottom: number;
|
|
16
16
|
paddingRight: number;
|
|
17
17
|
paddingLeft: number;
|
|
18
|
+
maxWidth: number;
|
|
18
19
|
focused?: boolean;
|
|
19
20
|
selected?: boolean;
|
|
20
21
|
children?: ReactChild[];
|
|
@@ -33,11 +34,11 @@ function getBackgroundColor({
|
|
|
33
34
|
backgroundColor,
|
|
34
35
|
focusedBackgroundColor,
|
|
35
36
|
selectedBackgroundColor,
|
|
36
|
-
|
|
37
|
+
focusedSelectedBackgroundColor,
|
|
37
38
|
}) {
|
|
38
39
|
switch (true) {
|
|
39
40
|
case selected && focused:
|
|
40
|
-
return
|
|
41
|
+
return focusedSelectedBackgroundColor;
|
|
41
42
|
case selected && !focused:
|
|
42
43
|
return selectedBackgroundColor;
|
|
43
44
|
case !selected && focused:
|
|
@@ -51,7 +52,7 @@ export function Item(props: ItemProps) {
|
|
|
51
52
|
const {
|
|
52
53
|
backgroundColor,
|
|
53
54
|
focusedBackgroundColor,
|
|
54
|
-
|
|
55
|
+
focusedSelectedBackgroundColor,
|
|
55
56
|
selectedBackgroundColor,
|
|
56
57
|
children,
|
|
57
58
|
focused,
|
|
@@ -68,7 +69,7 @@ export function Item(props: ItemProps) {
|
|
|
68
69
|
backgroundColor: getBackgroundColor({
|
|
69
70
|
selected,
|
|
70
71
|
focused,
|
|
71
|
-
|
|
72
|
+
focusedSelectedBackgroundColor,
|
|
72
73
|
focusedBackgroundColor,
|
|
73
74
|
selectedBackgroundColor,
|
|
74
75
|
backgroundColor,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
2
|
|
|
3
3
|
export const defaultSelectedAsset: string =
|
|
4
|
-
"data:image/png;base64,
|
|
4
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAA+0lEQVR4nO3a3QnCQBBF4ZRiSXZgKVqKnVnCQBpQwb0QJA752ZjszPlg3/JwOU8b2K4DAAAAAAAAkIOZnczsvPeOQypxHmb27Pv+sveeQxnG0SFSMRaHSIUXJ32kKXHKue+99e+I4yCOgzgO4jiI4yCOgzgO4jiajfMedd366t50nK3/b0LE2SpSqDi1I4WMUytSs3G6z/jbhOGLIzUdR7aKFCKO1I4UKo7UihQyjqyNFDqOLI2UIo7MjZQqjkyNVL7LFUdmRMoXRypEihtHVkSKH0cWRMoTR2ZEyhdHJkTKG0ecSMSRkUjE+TaIRJxfeFQJAAAAAAAANOwFT0Mt2UgcaMoAAAAASUVORK5CYII=";
|
|
@@ -3,7 +3,6 @@ import { StyleSheet, TouchableOpacity, View } from "react-native";
|
|
|
3
3
|
import { Item, ItemProps } from "./Item";
|
|
4
4
|
import { ItemIcon, ItemIconProps } from "./ItemIcon";
|
|
5
5
|
import { ItemLabel, ItemLabelProps } from "./ItemLabel";
|
|
6
|
-
import * as assets from "./assets";
|
|
7
6
|
import { defaultSelectedAsset } from "./assets";
|
|
8
7
|
|
|
9
8
|
type ButtonProps = {
|
|
@@ -17,6 +16,9 @@ type ButtonProps = {
|
|
|
17
16
|
labelBaseProps?: ItemLabelProps;
|
|
18
17
|
disabled?: boolean;
|
|
19
18
|
label?: string | Record<string, string>;
|
|
19
|
+
iconPlacement?: "left" | "right";
|
|
20
|
+
selectedItemIcon?: ItemIconProps["asset"];
|
|
21
|
+
defaultItemIcon?: ItemIconProps["asset"];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const styles = StyleSheet.create({
|
|
@@ -33,52 +35,32 @@ export function Button({
|
|
|
33
35
|
configuration,
|
|
34
36
|
width,
|
|
35
37
|
iconBaseProps,
|
|
36
|
-
itemBaseProps,
|
|
38
|
+
itemBaseProps: itemProps,
|
|
37
39
|
labelBaseProps,
|
|
38
40
|
label,
|
|
41
|
+
iconPlacement = "left",
|
|
42
|
+
defaultItemIcon,
|
|
43
|
+
selectedItemIcon,
|
|
39
44
|
disabled = false,
|
|
40
45
|
}: ButtonProps) {
|
|
41
46
|
const [focused, setFocused] = useState(false);
|
|
42
47
|
|
|
43
|
-
const selected =
|
|
44
|
-
() => selectedItem && item.value === selectedItem?.value,
|
|
45
|
-
[selectedItem, selectedItem]
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const itemProps = useMemo<ItemProps>(
|
|
49
|
-
() => ({
|
|
50
|
-
...itemBaseProps,
|
|
51
|
-
width,
|
|
52
|
-
}),
|
|
53
|
-
[configuration, width]
|
|
54
|
-
);
|
|
48
|
+
const selected = selectedItem && item.value === selectedItem?.value;
|
|
55
49
|
|
|
56
|
-
const
|
|
57
|
-
() =>
|
|
58
|
-
|
|
59
|
-
asset: configuration[item.asset] ?? assets[item.asset] ?? item.asset,
|
|
60
|
-
}),
|
|
61
|
-
[configuration, item.asset]
|
|
50
|
+
const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
51
|
+
() => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
|
|
52
|
+
[item.asset, defaultItemIcon]
|
|
62
53
|
);
|
|
63
54
|
|
|
64
|
-
const
|
|
65
|
-
() =>
|
|
66
|
-
|
|
67
|
-
asset:
|
|
68
|
-
configuration["modal_bottom_sheet_item_selected_icon"] ||
|
|
69
|
-
defaultSelectedAsset,
|
|
70
|
-
marginRight: 10,
|
|
71
|
-
}),
|
|
72
|
-
[configuration]
|
|
55
|
+
const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
56
|
+
() => selectedItemIcon || defaultSelectedAsset,
|
|
57
|
+
[selectedItemIcon]
|
|
73
58
|
);
|
|
74
59
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
...
|
|
78
|
-
|
|
79
|
-
}),
|
|
80
|
-
[configuration, item?.label]
|
|
81
|
-
);
|
|
60
|
+
const renderItemIcon =
|
|
61
|
+
itemIconPropsAssets && itemIconPropsAssets.length > 0 ? (
|
|
62
|
+
<ItemIcon {...iconBaseProps} asset={itemIconPropsAssets} />
|
|
63
|
+
) : null;
|
|
82
64
|
|
|
83
65
|
if (disabled) return null;
|
|
84
66
|
|
|
@@ -92,18 +74,23 @@ export function Button({
|
|
|
92
74
|
>
|
|
93
75
|
<Item {...itemProps} focused={focused} selected={selected}>
|
|
94
76
|
<View style={styles.label_icon_container}>
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{itemLabelProps.label ? (
|
|
77
|
+
{iconPlacement === "left" && renderItemIcon}
|
|
78
|
+
|
|
79
|
+
{label ? (
|
|
99
80
|
<ItemLabel
|
|
100
|
-
{...
|
|
81
|
+
{...labelBaseProps}
|
|
82
|
+
label={label ?? null}
|
|
101
83
|
focused={focused}
|
|
102
84
|
selected={selected}
|
|
103
85
|
/>
|
|
104
86
|
) : null}
|
|
105
87
|
</View>
|
|
106
|
-
|
|
88
|
+
|
|
89
|
+
{selected ? (
|
|
90
|
+
<ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
|
|
91
|
+
) : (
|
|
92
|
+
iconPlacement === "right" && renderItemIcon
|
|
93
|
+
)}
|
|
107
94
|
</Item>
|
|
108
95
|
</TouchableOpacity>
|
|
109
96
|
</View>
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
-
import { PluginConfiguration } from "./
|
|
2
|
+
import { PluginConfiguration } from "./";
|
|
3
|
+
import { ItemIconProps } from "./Button/ItemIcon";
|
|
4
|
+
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
5
|
+
import { ItemProps } from "./Button/Item";
|
|
3
6
|
|
|
4
7
|
export function defaultItemProps(
|
|
5
8
|
config: PluginConfiguration,
|
|
6
9
|
maxWidth: number
|
|
7
|
-
) {
|
|
10
|
+
): ItemProps {
|
|
8
11
|
const {
|
|
9
12
|
modal_bottom_sheet_item_background_color,
|
|
10
13
|
modal_bottom_sheet_item_focus_background_color,
|
|
11
14
|
modal_bottom_sheet_item_selected_background_color,
|
|
12
|
-
|
|
15
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
13
16
|
modal_bottom_sheet_item_corner_radius,
|
|
14
17
|
modal_bottom_sheet_item_margin_bottom,
|
|
15
18
|
modal_bottom_sheet_item_margin_left,
|
|
@@ -25,8 +28,8 @@ export function defaultItemProps(
|
|
|
25
28
|
backgroundColor: modal_bottom_sheet_item_background_color,
|
|
26
29
|
focusedBackgroundColor: modal_bottom_sheet_item_focus_background_color,
|
|
27
30
|
selectedBackgroundColor: modal_bottom_sheet_item_selected_background_color,
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
focusedSelectedBackgroundColor:
|
|
32
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
30
33
|
borderRadius: modal_bottom_sheet_item_corner_radius,
|
|
31
34
|
marginBottom: modal_bottom_sheet_item_margin_bottom,
|
|
32
35
|
marginTop: modal_bottom_sheet_item_margin_top,
|
|
@@ -43,7 +46,7 @@ export function defaultItemProps(
|
|
|
43
46
|
export function defaultItemLabelProps(
|
|
44
47
|
config: PluginConfiguration,
|
|
45
48
|
sheetWidth: number
|
|
46
|
-
) {
|
|
49
|
+
): ItemLabelProps {
|
|
47
50
|
const {
|
|
48
51
|
modal_bottom_sheet_item_label_android_letter_spacing,
|
|
49
52
|
modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
@@ -103,7 +106,9 @@ export function defaultItemLabelProps(
|
|
|
103
106
|
};
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
export function defaultItemIconProps(
|
|
109
|
+
export function defaultItemIconProps(
|
|
110
|
+
config: PluginConfiguration
|
|
111
|
+
): ItemIconProps {
|
|
107
112
|
const {
|
|
108
113
|
modal_bottom_sheet_item_icon_height,
|
|
109
114
|
modal_bottom_sheet_item_icon_width,
|
|
@@ -124,3 +129,46 @@ export function defaultItemIconProps(config: PluginConfiguration) {
|
|
|
124
129
|
marginRight: modal_bottom_sheet_item_icon_margin_right,
|
|
125
130
|
};
|
|
126
131
|
}
|
|
132
|
+
|
|
133
|
+
export function getItemIconProps(
|
|
134
|
+
theme: PluginConfiguration,
|
|
135
|
+
iconProps?: ((theme: PluginConfiguration) => ItemIconProps) | ItemIconProps
|
|
136
|
+
) {
|
|
137
|
+
if (iconProps) {
|
|
138
|
+
return typeof iconProps === "function" ? iconProps(theme) : iconProps;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return defaultItemIconProps(theme);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getItemLabelProps(
|
|
145
|
+
theme: PluginConfiguration,
|
|
146
|
+
width: number,
|
|
147
|
+
labelProps?:
|
|
148
|
+
| ((theme: PluginConfiguration, width: number) => ItemLabelProps)
|
|
149
|
+
| ItemLabelProps
|
|
150
|
+
) {
|
|
151
|
+
if (labelProps) {
|
|
152
|
+
return typeof labelProps === "function"
|
|
153
|
+
? labelProps(theme, width)
|
|
154
|
+
: labelProps;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return defaultItemLabelProps(theme, width);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function getItemProps(
|
|
161
|
+
theme: PluginConfiguration,
|
|
162
|
+
width: number,
|
|
163
|
+
itemProps?:
|
|
164
|
+
| ((theme: PluginConfiguration, width: number) => ItemProps)
|
|
165
|
+
| ItemProps
|
|
166
|
+
) {
|
|
167
|
+
if (itemProps) {
|
|
168
|
+
return typeof itemProps === "function"
|
|
169
|
+
? itemProps(theme, width)
|
|
170
|
+
: itemProps;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return defaultItemProps(theme, width);
|
|
174
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Text, Animated } from "react-native";
|
|
3
3
|
|
|
4
|
-
import { shallow } from "enzyme";
|
|
5
4
|
import renderer from "react-test-renderer";
|
|
6
5
|
|
|
7
6
|
jest.useFakeTimers();
|
|
@@ -40,10 +39,6 @@ const {
|
|
|
40
39
|
} = require("../NotificationView");
|
|
41
40
|
|
|
42
41
|
describe("NotificationView", () => {
|
|
43
|
-
it("renders", () => {
|
|
44
|
-
shallow(<NotificationView dismiss={dismiss} />);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
42
|
it("Show online message when Online", () => {
|
|
48
43
|
const component = renderer.create(
|
|
49
44
|
<NotificationView online dismiss={dismiss} />
|
|
@@ -57,7 +57,7 @@ export const useNotificationHeight = () => {
|
|
|
57
57
|
|
|
58
58
|
const navBarHeight = platformSelect({ ios: 44, android: 56 });
|
|
59
59
|
|
|
60
|
-
const statusHeight =
|
|
60
|
+
const statusHeight = insets.top;
|
|
61
61
|
const notificationHeight = statusHeight + navBarHeight;
|
|
62
62
|
|
|
63
63
|
return { statusHeight, notificationHeight };
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
isApplePlatform,
|
|
10
10
|
isTV,
|
|
11
11
|
platformSelect,
|
|
12
|
+
isAndroidTVPlatform,
|
|
12
13
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
13
14
|
|
|
14
15
|
import { TVEventHandlerComponent } from "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent";
|
|
@@ -93,6 +94,20 @@ export type PlayNextData = {
|
|
|
93
94
|
|
|
94
95
|
const focusableBottomContainerId = "player-container-bottom";
|
|
95
96
|
|
|
97
|
+
const isAndroidTV = isAndroidTVPlatform();
|
|
98
|
+
|
|
99
|
+
const withBorderHack = () => {
|
|
100
|
+
if (isAndroidTV) {
|
|
101
|
+
/* @HACK: see GH#7269 */
|
|
102
|
+
return {
|
|
103
|
+
borderWidth: 1,
|
|
104
|
+
borderColor: "transparent",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {};
|
|
109
|
+
};
|
|
110
|
+
|
|
96
111
|
// Styles
|
|
97
112
|
const webStyles = {
|
|
98
113
|
focusableGroup: {
|
|
@@ -335,9 +350,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
335
350
|
|
|
336
351
|
const resumeTime = Number(item?.extensions?.resumeTime);
|
|
337
352
|
|
|
338
|
-
//
|
|
353
|
+
// Сhecking that the player itself knows where to start playing, and there is no need to call seekTo after returning from the Сhromecast
|
|
339
354
|
if (
|
|
340
|
-
|
|
355
|
+
!playerManager.getActivePlayer()?.hasResumePosition() &&
|
|
341
356
|
!isNaN(resumeTime)
|
|
342
357
|
) {
|
|
343
358
|
player?.seekTo(resumeTime);
|
|
@@ -514,6 +529,12 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
514
529
|
useEffect(() => {
|
|
515
530
|
playerEvent("source_changed", { item });
|
|
516
531
|
|
|
532
|
+
return () => {
|
|
533
|
+
playerEvent("player_did_close", { item });
|
|
534
|
+
};
|
|
535
|
+
}, [item?.id, Player]);
|
|
536
|
+
|
|
537
|
+
useEffect(() => {
|
|
517
538
|
if (!isModal) {
|
|
518
539
|
showNavBar(false);
|
|
519
540
|
}
|
|
@@ -523,13 +544,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
523
544
|
}
|
|
524
545
|
|
|
525
546
|
return () => {
|
|
526
|
-
playerEvent("player_did_close", { item });
|
|
527
|
-
|
|
528
547
|
if (!isModal) {
|
|
529
548
|
showNavBar(true);
|
|
530
549
|
}
|
|
531
550
|
};
|
|
532
|
-
}, [showNavBar,
|
|
551
|
+
}, [showNavBar, isModal, Player]);
|
|
533
552
|
|
|
534
553
|
useEffect(() => {
|
|
535
554
|
if (prevItemId && !R.equals(prevItemId, item?.id)) {
|
|
@@ -640,7 +659,14 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
640
659
|
testID={"player-screen-container"}
|
|
641
660
|
>
|
|
642
661
|
{/* Player container */}
|
|
643
|
-
<View
|
|
662
|
+
<View
|
|
663
|
+
style={[
|
|
664
|
+
styles.playerWrapper,
|
|
665
|
+
// eslint-disable-next-line react-native/no-inline-styles, react-native/no-color-literals
|
|
666
|
+
withBorderHack(),
|
|
667
|
+
]}
|
|
668
|
+
testID={"player-wrapper"}
|
|
669
|
+
>
|
|
644
670
|
<PlayerFocusableWrapperView
|
|
645
671
|
nextFocusDown={context.bottomFocusableId}
|
|
646
672
|
>
|