@applicaster/zapp-react-native-ui-components 12.0.0-rc.6 → 12.0.0-rc.60
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/AudioPlayer/AudioPlayer.tsx +9 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/Cell/Cell.tsx +2 -2
- package/Components/Cell/CellWithFocusable.tsx +21 -14
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableList/FocusableChild.ts +24 -14
- package/Components/FocusableList/FocusableItem.tsx +1 -1
- package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
- package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
- package/Components/FocusableList/index.tsx +26 -25
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +11 -8
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +1 -1
- package/Components/HookRenderer/index.tsx +1 -6
- package/Components/Image/Image.android.tsx +3 -26
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/__tests__/index.test.tsx +1 -34
- package/Components/Layout/TV/index.tsx +20 -36
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- package/Components/MasterCell/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/Toggle.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -10
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/utils/index.ts +16 -5
- package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
- package/Components/ModalComponent/Button/Item.tsx +82 -0
- package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
- package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
- package/Components/ModalComponent/Button/assets.ts +4 -0
- package/Components/ModalComponent/Button/index.tsx +111 -0
- package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
- package/Components/ModalComponent/Header/Title.tsx +70 -0
- package/Components/ModalComponent/Header/assets.ts +4 -0
- package/Components/ModalComponent/Header/index.tsx +71 -0
- package/Components/ModalComponent/Header/utils.ts +79 -0
- package/Components/ModalComponent/index.tsx +38 -0
- package/Components/ModalComponent/utils.ts +126 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +61 -30
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +91 -2
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/River.tsx +8 -5
- package/Components/River/TV/River.tsx +2 -2
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/River/useScreenConfiguration.ts +5 -6
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
- package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
- package/Components/RouteManager/index.tsx +5 -3
- package/Components/Screen/__tests__/Screen.test.tsx +48 -36
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
- package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
- package/Components/Screen/index.tsx +103 -44
- package/Components/Screen/navigationHandler.ts +0 -82
- package/Components/Screen/orientationHandler.ts +1 -1
- package/Components/ScreenResolver/index.tsx +1 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/VideoLive/LiveImageManager.ts +42 -13
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +81 -72
- 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/PlayerDetails.tsx +3 -0
- package/Components/VideoModal/PlayerWrapper.tsx +69 -44
- package/Components/VideoModal/VideoModal.tsx +25 -42
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +5 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/hooks/useModalSize.ts +13 -4
- package/Components/VideoModal/utils.ts +3 -3
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +1 -1
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Components/ZappUIComponent/index.tsx +22 -12
- package/Components/index.js +2 -0
- 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 +95 -29
- package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/Decorators/RiverResolver/index.tsx +0 -4
- package/Decorators/index.tsx +0 -4
- package/events/index.ts +1 -0
- package/package.json +5 -6
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as R from "ramda";
|
|
2
|
+
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
+
import { PluginConfiguration } from "../index";
|
|
4
|
+
|
|
5
|
+
export function getCloseButtonProps(config: PluginConfiguration) {
|
|
6
|
+
const {
|
|
7
|
+
modal_bottom_sheet_close_asset,
|
|
8
|
+
modal_bottom_sheet_close_focus_asset,
|
|
9
|
+
modal_bottom_sheet_close_height,
|
|
10
|
+
modal_bottom_sheet_close_width,
|
|
11
|
+
modal_bottom_sheet_close_switch,
|
|
12
|
+
modal_bottom_sheet_close_margin_bottom,
|
|
13
|
+
modal_bottom_sheet_close_margin_left,
|
|
14
|
+
modal_bottom_sheet_close_margin_right,
|
|
15
|
+
modal_bottom_sheet_close_margin_top,
|
|
16
|
+
} = config;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
asset: modal_bottom_sheet_close_asset,
|
|
20
|
+
assetFocused: modal_bottom_sheet_close_focus_asset,
|
|
21
|
+
enabled: modal_bottom_sheet_close_switch,
|
|
22
|
+
width: modal_bottom_sheet_close_width,
|
|
23
|
+
height: modal_bottom_sheet_close_height,
|
|
24
|
+
marginTop: modal_bottom_sheet_close_margin_top,
|
|
25
|
+
marginBottom: modal_bottom_sheet_close_margin_bottom,
|
|
26
|
+
marginLeft: modal_bottom_sheet_close_margin_left,
|
|
27
|
+
marginRight: modal_bottom_sheet_close_margin_right,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getTextValue(
|
|
32
|
+
config: PluginConfiguration,
|
|
33
|
+
entry: ZappEntry,
|
|
34
|
+
key: string
|
|
35
|
+
): string {
|
|
36
|
+
const keyValue = config[key];
|
|
37
|
+
|
|
38
|
+
if (entry) {
|
|
39
|
+
const keyPath = R.split(".", keyValue);
|
|
40
|
+
|
|
41
|
+
return R.path(keyPath, entry);
|
|
42
|
+
} else {
|
|
43
|
+
return keyValue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getConfigKey(
|
|
48
|
+
config: PluginConfiguration,
|
|
49
|
+
suffix: string,
|
|
50
|
+
key: "title" | "summary"
|
|
51
|
+
) {
|
|
52
|
+
return config?.[`modal_bottom_sheet_${key}_${suffix}`];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getTitleProps(
|
|
56
|
+
config: PluginConfiguration,
|
|
57
|
+
key: "title" | "summary"
|
|
58
|
+
) {
|
|
59
|
+
return {
|
|
60
|
+
enabled: getConfigKey(config, "switch", key),
|
|
61
|
+
letterSpacing: platformSelect({
|
|
62
|
+
ios: getConfigKey(config, "ios_letter_spacing", key),
|
|
63
|
+
android: getConfigKey(config, "android_letter_spacing", key),
|
|
64
|
+
}),
|
|
65
|
+
fontFamily: platformSelect({
|
|
66
|
+
ios: getConfigKey(config, "family_ios_font_selector", key),
|
|
67
|
+
android: getConfigKey(config, "family_android_font_selector", key),
|
|
68
|
+
}),
|
|
69
|
+
lineHeight: getConfigKey(config, "line_height", key),
|
|
70
|
+
fontSize: getConfigKey(config, "font_size", key),
|
|
71
|
+
color: getConfigKey(config, "font_color", key),
|
|
72
|
+
marginTop: getConfigKey(config, "margin_top", key),
|
|
73
|
+
marginBottom: getConfigKey(config, "margin_bottom", key),
|
|
74
|
+
marginLeft: getConfigKey(config, "margin_left", key),
|
|
75
|
+
marginRight: getConfigKey(config, "margin_right", key),
|
|
76
|
+
numberOfLines: getConfigKey(config, "number_of_lines", key),
|
|
77
|
+
transform: getConfigKey(config, "transform", key),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useCallback, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { BasicMeasurementsPortal as MeasurementsPortal } from "@applicaster/zapp-react-native-ui-components/Components/MeasurmentsPortal";
|
|
4
|
+
import { BottomSheetModalContent } from "./BottomSheetModalContent";
|
|
5
|
+
|
|
6
|
+
export type PluginConfiguration = {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
actionPlugins?: [QuickBrickPlugin];
|
|
12
|
+
configuration?: PluginConfiguration;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function ModalComponent(props: ModalBottomSheetContentProps & Props) {
|
|
16
|
+
const [height, setHeight] = useState(0);
|
|
17
|
+
|
|
18
|
+
const onLayout = useCallback(
|
|
19
|
+
({ nativeEvent }) => {
|
|
20
|
+
if (height === 0) {
|
|
21
|
+
setHeight(nativeEvent.layout.height);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
[height]
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (height === 0) {
|
|
28
|
+
return (
|
|
29
|
+
<MeasurementsPortal
|
|
30
|
+
Component={BottomSheetModalContent}
|
|
31
|
+
componentProps={props}
|
|
32
|
+
onLayout={onLayout}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return <BottomSheetModalContent {...props} />;
|
|
38
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
+
import { PluginConfiguration } from "./index";
|
|
3
|
+
|
|
4
|
+
export function defaultItemProps(
|
|
5
|
+
config: PluginConfiguration,
|
|
6
|
+
maxWidth: number
|
|
7
|
+
) {
|
|
8
|
+
const {
|
|
9
|
+
modal_bottom_sheet_item_background_color,
|
|
10
|
+
modal_bottom_sheet_item_focus_background_color,
|
|
11
|
+
modal_bottom_sheet_item_selected_background_color,
|
|
12
|
+
modal_bottom_sheet_item_focusected_background_color,
|
|
13
|
+
modal_bottom_sheet_item_corner_radius,
|
|
14
|
+
modal_bottom_sheet_item_margin_bottom,
|
|
15
|
+
modal_bottom_sheet_item_margin_left,
|
|
16
|
+
modal_bottom_sheet_item_margin_right,
|
|
17
|
+
modal_bottom_sheet_item_margin_top,
|
|
18
|
+
modal_bottom_sheet_item_padding_bottom,
|
|
19
|
+
modal_bottom_sheet_item_padding_left,
|
|
20
|
+
modal_bottom_sheet_item_padding_right,
|
|
21
|
+
modal_bottom_sheet_item_padding_top,
|
|
22
|
+
} = config;
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
backgroundColor: modal_bottom_sheet_item_background_color,
|
|
26
|
+
focusedBackgroundColor: modal_bottom_sheet_item_focus_background_color,
|
|
27
|
+
selectedBackgroundColor: modal_bottom_sheet_item_selected_background_color,
|
|
28
|
+
focusectedBackgroundColor:
|
|
29
|
+
modal_bottom_sheet_item_focusected_background_color,
|
|
30
|
+
borderRadius: modal_bottom_sheet_item_corner_radius,
|
|
31
|
+
marginBottom: modal_bottom_sheet_item_margin_bottom,
|
|
32
|
+
marginTop: modal_bottom_sheet_item_margin_top,
|
|
33
|
+
marginLeft: modal_bottom_sheet_item_margin_left,
|
|
34
|
+
marginRight: modal_bottom_sheet_item_margin_right,
|
|
35
|
+
paddingTop: modal_bottom_sheet_item_padding_top,
|
|
36
|
+
paddingBottom: modal_bottom_sheet_item_padding_bottom,
|
|
37
|
+
paddingRight: modal_bottom_sheet_item_padding_right,
|
|
38
|
+
paddingLeft: modal_bottom_sheet_item_padding_left,
|
|
39
|
+
maxWidth,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function defaultItemLabelProps(
|
|
44
|
+
config: PluginConfiguration,
|
|
45
|
+
sheetWidth: number
|
|
46
|
+
) {
|
|
47
|
+
const {
|
|
48
|
+
modal_bottom_sheet_item_label_android_letter_spacing,
|
|
49
|
+
modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
50
|
+
modal_bottom_sheet_item_label_family_ios_font_selector,
|
|
51
|
+
modal_bottom_sheet_item_label_family_android_font_selector,
|
|
52
|
+
modal_bottom_sheet_item_label_focus_font_color,
|
|
53
|
+
modal_bottom_sheet_item_label_font_color,
|
|
54
|
+
modal_bottom_sheet_item_label_selected_font_color,
|
|
55
|
+
modal_bottom_sheet_item_label_hover_selected_font_color,
|
|
56
|
+
modal_bottom_sheet_item_label_font_size,
|
|
57
|
+
modal_bottom_sheet_item_label_line_height,
|
|
58
|
+
modal_bottom_sheet_item_label_margin_bottom,
|
|
59
|
+
modal_bottom_sheet_item_label_margin_top,
|
|
60
|
+
modal_bottom_sheet_item_label_margin_left,
|
|
61
|
+
modal_bottom_sheet_item_label_margin_right,
|
|
62
|
+
modal_bottom_sheet_item_label_transform,
|
|
63
|
+
modal_bottom_sheet_item_icon_width,
|
|
64
|
+
modal_bottom_sheet_item_icon_margin_left,
|
|
65
|
+
modal_bottom_sheet_item_icon_margin_right,
|
|
66
|
+
modal_bottom_sheet_item_margin_left,
|
|
67
|
+
modal_bottom_sheet_item_margin_right,
|
|
68
|
+
modal_bottom_sheet_item_padding_left,
|
|
69
|
+
modal_bottom_sheet_item_padding_right,
|
|
70
|
+
} = config;
|
|
71
|
+
|
|
72
|
+
const maxWidth =
|
|
73
|
+
sheetWidth -
|
|
74
|
+
(modal_bottom_sheet_item_icon_width +
|
|
75
|
+
modal_bottom_sheet_item_icon_margin_left +
|
|
76
|
+
modal_bottom_sheet_item_icon_margin_right +
|
|
77
|
+
modal_bottom_sheet_item_margin_left +
|
|
78
|
+
modal_bottom_sheet_item_margin_right +
|
|
79
|
+
modal_bottom_sheet_item_padding_left +
|
|
80
|
+
modal_bottom_sheet_item_padding_right);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
fontFamily: platformSelect({
|
|
84
|
+
ios: modal_bottom_sheet_item_label_family_ios_font_selector,
|
|
85
|
+
android: modal_bottom_sheet_item_label_family_android_font_selector,
|
|
86
|
+
}),
|
|
87
|
+
letterSpacing: platformSelect({
|
|
88
|
+
ios: modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
89
|
+
android: modal_bottom_sheet_item_label_android_letter_spacing,
|
|
90
|
+
}),
|
|
91
|
+
fontSize: modal_bottom_sheet_item_label_font_size,
|
|
92
|
+
color: modal_bottom_sheet_item_label_font_color,
|
|
93
|
+
focusColor: modal_bottom_sheet_item_label_focus_font_color,
|
|
94
|
+
hoverSelectedColor: modal_bottom_sheet_item_label_hover_selected_font_color,
|
|
95
|
+
selectedColor: modal_bottom_sheet_item_label_selected_font_color,
|
|
96
|
+
lineHeight: modal_bottom_sheet_item_label_line_height,
|
|
97
|
+
marginBottom: modal_bottom_sheet_item_label_margin_bottom,
|
|
98
|
+
marginTop: modal_bottom_sheet_item_label_margin_top,
|
|
99
|
+
marginLeft: modal_bottom_sheet_item_label_margin_left,
|
|
100
|
+
marginRight: modal_bottom_sheet_item_label_margin_right,
|
|
101
|
+
transform: modal_bottom_sheet_item_label_transform,
|
|
102
|
+
maxWidth,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function defaultItemIconProps(config: PluginConfiguration) {
|
|
107
|
+
const {
|
|
108
|
+
modal_bottom_sheet_item_icon_height,
|
|
109
|
+
modal_bottom_sheet_item_icon_width,
|
|
110
|
+
modal_bottom_sheet_item_icon_margin_bottom,
|
|
111
|
+
modal_bottom_sheet_item_icon_margin_left,
|
|
112
|
+
modal_bottom_sheet_item_icon_margin_right,
|
|
113
|
+
modal_bottom_sheet_item_icon_margin_top,
|
|
114
|
+
modal_bottom_sheet_item_icon_flavour,
|
|
115
|
+
} = config;
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
width: modal_bottom_sheet_item_icon_width,
|
|
119
|
+
height: modal_bottom_sheet_item_icon_height,
|
|
120
|
+
flavour: modal_bottom_sheet_item_icon_flavour,
|
|
121
|
+
marginTop: modal_bottom_sheet_item_icon_margin_top,
|
|
122
|
+
marginBottom: modal_bottom_sheet_item_icon_margin_bottom,
|
|
123
|
+
marginLeft: modal_bottom_sheet_item_icon_margin_left,
|
|
124
|
+
marginRight: modal_bottom_sheet_item_icon_margin_right,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -54,6 +54,11 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
|
54
54
|
import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
|
|
55
55
|
import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
|
|
56
56
|
|
|
57
|
+
import {
|
|
58
|
+
useModalAnimationContext,
|
|
59
|
+
PlayerAnimationStateEnum,
|
|
60
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
61
|
+
|
|
57
62
|
type Props = {
|
|
58
63
|
Player: React.ComponentType<any>;
|
|
59
64
|
PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
|
|
@@ -145,34 +150,30 @@ const renderApplePlayer = ({
|
|
|
145
150
|
}) => {
|
|
146
151
|
const { title, summary } = item || {};
|
|
147
152
|
|
|
148
|
-
if (!
|
|
153
|
+
if (!isAppleTV() || !player) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isAudioContent) {
|
|
158
|
+
return (
|
|
159
|
+
<AudioPlayer
|
|
160
|
+
audio_item={item}
|
|
161
|
+
plugin_configuration={pluginConfiguration}
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!playNextData && player.isPaused() && player.isAd() === false) {
|
|
149
167
|
return null;
|
|
150
168
|
}
|
|
151
169
|
|
|
152
170
|
return (
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
<ProgramInfo
|
|
160
|
-
title={title}
|
|
161
|
-
subtitle={summary}
|
|
162
|
-
plugin_configuration={pluginConfiguration}
|
|
163
|
-
videoStyle={videoStyle}
|
|
164
|
-
/>
|
|
165
|
-
)}
|
|
166
|
-
</>
|
|
167
|
-
)}
|
|
168
|
-
|
|
169
|
-
{isAudioContent && (
|
|
170
|
-
<AudioPlayer
|
|
171
|
-
audio_item={item}
|
|
172
|
-
plugin_configuration={pluginConfiguration}
|
|
173
|
-
/>
|
|
174
|
-
)}
|
|
175
|
-
</>
|
|
171
|
+
<ProgramInfo
|
|
172
|
+
title={title}
|
|
173
|
+
subtitle={summary}
|
|
174
|
+
plugin_configuration={pluginConfiguration}
|
|
175
|
+
videoStyle={videoStyle}
|
|
176
|
+
/>
|
|
176
177
|
);
|
|
177
178
|
};
|
|
178
179
|
|
|
@@ -233,6 +234,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
233
234
|
const screenData = useTargetScreenData(item);
|
|
234
235
|
const { setVisible: showNavBar } = useSetNavbarState();
|
|
235
236
|
|
|
237
|
+
const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
|
|
238
|
+
useModalAnimationContext();
|
|
239
|
+
|
|
236
240
|
const playerEvent = (event, ...args) => {
|
|
237
241
|
playerManager.invokeHandler(event, ...args);
|
|
238
242
|
};
|
|
@@ -339,6 +343,18 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
339
343
|
}
|
|
340
344
|
}, [item?.id, item?.extensions?.resumeTime, player]);
|
|
341
345
|
|
|
346
|
+
const onVideoFullscreenPlayerWillPresent = React.useCallback(() => {
|
|
347
|
+
playerManager.invokeHandler("toggleFullscreen", {
|
|
348
|
+
fullscreen: true,
|
|
349
|
+
});
|
|
350
|
+
}, []);
|
|
351
|
+
|
|
352
|
+
const onVideoFullscreenPlayerWillDismiss = React.useCallback(() => {
|
|
353
|
+
playerManager.invokeHandler("toggleFullscreen", {
|
|
354
|
+
fullscreen: false,
|
|
355
|
+
});
|
|
356
|
+
}, []);
|
|
357
|
+
|
|
342
358
|
// Util methods
|
|
343
359
|
const toggleFullscreen = (event) => {
|
|
344
360
|
const { fullscreen = false } = event || {};
|
|
@@ -381,17 +397,27 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
381
397
|
id: playerContainerId,
|
|
382
398
|
listener: {
|
|
383
399
|
onVideoEnd,
|
|
384
|
-
onError
|
|
385
|
-
onLoad
|
|
400
|
+
onError,
|
|
401
|
+
onLoad,
|
|
386
402
|
onPlayerClose: close,
|
|
387
403
|
onPlayerDetached: close,
|
|
404
|
+
onVideoFullscreenPlayerWillDismiss,
|
|
405
|
+
onVideoFullscreenPlayerWillPresent,
|
|
388
406
|
},
|
|
389
407
|
});
|
|
390
408
|
|
|
391
409
|
return () => {
|
|
392
410
|
player.removeListener(playerContainerId);
|
|
393
411
|
};
|
|
394
|
-
}, [
|
|
412
|
+
}, [
|
|
413
|
+
player,
|
|
414
|
+
onVideoEnd,
|
|
415
|
+
onError,
|
|
416
|
+
onLoad,
|
|
417
|
+
close,
|
|
418
|
+
onVideoFullscreenPlayerWillDismiss,
|
|
419
|
+
onVideoFullscreenPlayerWillPresent,
|
|
420
|
+
]);
|
|
395
421
|
|
|
396
422
|
useEffect(() => {
|
|
397
423
|
// TODO: We should not use playerManager here to connect buttons to player container
|
|
@@ -428,7 +454,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
428
454
|
if (disableMiniPlayer) {
|
|
429
455
|
navigator.closeVideoModal();
|
|
430
456
|
} else {
|
|
431
|
-
|
|
457
|
+
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
432
458
|
}
|
|
433
459
|
}
|
|
434
460
|
|
|
@@ -621,9 +647,13 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
621
647
|
}}
|
|
622
648
|
focused={isInlineTV ? true : undefined}
|
|
623
649
|
autoplay={true}
|
|
624
|
-
controls={
|
|
650
|
+
controls={false}
|
|
625
651
|
disableCastAction={disableCastAction}
|
|
626
|
-
docked={
|
|
652
|
+
docked={
|
|
653
|
+
navigator.isVideoModalDocked() &&
|
|
654
|
+
!startComponentsAnimation &&
|
|
655
|
+
!isActiveGesture
|
|
656
|
+
}
|
|
627
657
|
entry={item}
|
|
628
658
|
fullscreen={mode === VideoModalMode.FULLSCREEN}
|
|
629
659
|
inline={inline}
|
|
@@ -641,6 +671,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
641
671
|
setNextVideoPreloadThresholdPercentage={
|
|
642
672
|
setNextVideoPreloadThresholdPercentage
|
|
643
673
|
}
|
|
674
|
+
startComponentsAnimation={startComponentsAnimation}
|
|
644
675
|
>
|
|
645
676
|
{renderApplePlayer(applePlayerProps)}
|
|
646
677
|
</Player>
|
|
@@ -4,7 +4,9 @@ import { styleKeys } from "@applicaster/zapp-react-native-utils/styleKeysUtils";
|
|
|
4
4
|
import { transformColorCode as fixColorHexCode } from "@applicaster/zapp-react-native-utils/transform";
|
|
5
5
|
import * as R from "ramda";
|
|
6
6
|
import * as React from "react";
|
|
7
|
-
import {
|
|
7
|
+
import { Text, TextStyle, View, ViewStyle } from "react-native";
|
|
8
|
+
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
9
|
+
|
|
8
10
|
import * as programStyles from "./styles";
|
|
9
11
|
|
|
10
12
|
type Props = {
|
|
@@ -1,38 +1,64 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
import { ImageBackground } from "react-native";
|
|
2
|
+
import { ImageBackground, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
|
+
import {
|
|
6
|
+
AnimationComponent,
|
|
7
|
+
ComponentAnimationType,
|
|
8
|
+
useModalAnimationContext,
|
|
9
|
+
PlayerAnimationStateEnum,
|
|
10
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
5
11
|
|
|
6
12
|
type Props = PropsWithChildren<{
|
|
7
13
|
entry: ZappEntry;
|
|
8
14
|
style?: { [K: string]: any };
|
|
9
15
|
imageStyle?: { [K: string]: any };
|
|
10
16
|
imageKey?: string;
|
|
17
|
+
defaultImageDimensions?: { [K: string]: any };
|
|
11
18
|
}>;
|
|
12
19
|
|
|
20
|
+
const imageSize = { width: "100%", height: "100%" };
|
|
21
|
+
|
|
13
22
|
const PlayerImageBackgroundComponent = ({
|
|
14
23
|
entry,
|
|
15
24
|
children,
|
|
16
25
|
style,
|
|
17
26
|
imageStyle,
|
|
18
27
|
imageKey,
|
|
28
|
+
defaultImageDimensions,
|
|
19
29
|
}: Props) => {
|
|
20
30
|
const source = React.useMemo(
|
|
21
31
|
() => ({ uri: imageSrcFromMediaItem(entry, imageKey) }),
|
|
22
32
|
[imageKey, entry]
|
|
23
33
|
);
|
|
24
34
|
|
|
35
|
+
const { playerAnimationState } = useModalAnimationContext();
|
|
36
|
+
|
|
25
37
|
if (!source) return <>{children}</>;
|
|
26
38
|
|
|
27
39
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
<View
|
|
41
|
+
style={
|
|
42
|
+
playerAnimationState === PlayerAnimationStateEnum.maximaze
|
|
43
|
+
? defaultImageDimensions
|
|
44
|
+
: style
|
|
45
|
+
}
|
|
33
46
|
>
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
<AnimationComponent
|
|
48
|
+
style={style}
|
|
49
|
+
animationType={ComponentAnimationType.player}
|
|
50
|
+
additionalData={defaultImageDimensions}
|
|
51
|
+
>
|
|
52
|
+
<ImageBackground
|
|
53
|
+
resizeMode="cover"
|
|
54
|
+
style={imageSize}
|
|
55
|
+
imageStyle={imageStyle}
|
|
56
|
+
source={source}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</ImageBackground>
|
|
60
|
+
</AnimationComponent>
|
|
61
|
+
</View>
|
|
36
62
|
);
|
|
37
63
|
};
|
|
38
64
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
-
import { View,
|
|
3
|
+
import { View, StyleSheet, Platform, FlatList } from "react-native";
|
|
4
4
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
5
5
|
import { RiverItem } from "../RiverItem";
|
|
6
6
|
import { RiverFooter } from "../RiverFooter";
|
|
@@ -21,6 +21,8 @@ import {
|
|
|
21
21
|
import { useScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenData";
|
|
22
22
|
import { isLast } from "@applicaster/zapp-react-native-utils/arrayUtils";
|
|
23
23
|
import { withComponentsMapProvider } from "@applicaster/zapp-react-native-ui-components/Decorators/ComponentsMapWrapper";
|
|
24
|
+
import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
25
|
+
import { useShallow } from "zustand/react/shallow";
|
|
24
26
|
|
|
25
27
|
type Props = {
|
|
26
28
|
feed: ZappFeed;
|
|
@@ -40,8 +42,10 @@ const styles = StyleSheet.create({
|
|
|
40
42
|
},
|
|
41
43
|
});
|
|
42
44
|
|
|
43
|
-
const
|
|
45
|
+
const getNearestValue = (value, optionA, optionB) =>
|
|
46
|
+
Math.abs(value - optionA) < Math.abs(value - optionB) ? optionA : optionB;
|
|
44
47
|
|
|
48
|
+
const scrollIndicatorInsets = { right: 1 };
|
|
45
49
|
const keyExtractor = R.compose(String, R.prop("id"));
|
|
46
50
|
|
|
47
51
|
function ComponentsMapComponent(props: Props) {
|
|
@@ -59,6 +63,7 @@ function ComponentsMapComponent(props: Props) {
|
|
|
59
63
|
refreshingPipesV1,
|
|
60
64
|
} = props;
|
|
61
65
|
|
|
66
|
+
const flatListRef = React.useRef<FlatList | null>(null);
|
|
62
67
|
const screenConfig = useScreenConfiguration(riverId);
|
|
63
68
|
const screenData = useScreenData(riverId);
|
|
64
69
|
const pullToRefreshEnabled = screenData?.rules?.pull_to_refresh_enabled;
|
|
@@ -193,6 +198,82 @@ function ComponentsMapComponent(props: Props) {
|
|
|
193
198
|
[]
|
|
194
199
|
);
|
|
195
200
|
|
|
201
|
+
const navBarStore = useScreenContextV2()._navBarStore;
|
|
202
|
+
|
|
203
|
+
const scrollY = navBarStore(
|
|
204
|
+
useShallow(({ scrollYAnimated }) => scrollYAnimated)
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const canMomentum = React.useRef(false);
|
|
208
|
+
|
|
209
|
+
const onScrollBeginDrag = React.useCallback(() => {
|
|
210
|
+
canMomentum.current = true;
|
|
211
|
+
}, []);
|
|
212
|
+
|
|
213
|
+
/* onMomentumScrollEnd: Handling snap to expanded/collapsed state ( for navbar ) */
|
|
214
|
+
const _onMomentumScrollEnd = React.useCallback(({ nativeEvent }) => {
|
|
215
|
+
if (!canMomentum.current) return;
|
|
216
|
+
canMomentum.current = false;
|
|
217
|
+
|
|
218
|
+
const { height: headerHeight, scrollState } = navBarStore.getState();
|
|
219
|
+
|
|
220
|
+
const offsetY = Math.max(0, nativeEvent.contentOffset.y);
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
!(scrollState === 0 || scrollState === -headerHeight) &&
|
|
224
|
+
flatListRef.current
|
|
225
|
+
) {
|
|
226
|
+
const offset =
|
|
227
|
+
getNearestValue(Math.round(scrollState), -headerHeight, 0) ===
|
|
228
|
+
-headerHeight
|
|
229
|
+
? Math.round(offsetY + scrollState + headerHeight)
|
|
230
|
+
: Math.round(offsetY + scrollState);
|
|
231
|
+
|
|
232
|
+
flatListRef.current.scrollToOffset({
|
|
233
|
+
animated: true,
|
|
234
|
+
offset,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}, []);
|
|
238
|
+
|
|
239
|
+
/* onScrollEnd: Handling snap to expanded/collapsed state ( for navbar ) */
|
|
240
|
+
const _onScrollEndDrag = React.useCallback(({ nativeEvent }) => {
|
|
241
|
+
const { height: headerHeight, scrollState } = navBarStore.getState();
|
|
242
|
+
|
|
243
|
+
const offsetY = Math.max(0, nativeEvent.contentOffset.y);
|
|
244
|
+
|
|
245
|
+
if (
|
|
246
|
+
!(scrollState === 0 || scrollState === -headerHeight) &&
|
|
247
|
+
flatListRef.current &&
|
|
248
|
+
nativeEvent.velocity.y === 0
|
|
249
|
+
) {
|
|
250
|
+
const offset =
|
|
251
|
+
getNearestValue(Math.round(scrollState), -headerHeight, 0) ===
|
|
252
|
+
-headerHeight
|
|
253
|
+
? Math.round(offsetY + scrollState + headerHeight)
|
|
254
|
+
: Math.round(offsetY + scrollState);
|
|
255
|
+
|
|
256
|
+
flatListRef.current.scrollToOffset({
|
|
257
|
+
animated: true,
|
|
258
|
+
offset,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}, []);
|
|
262
|
+
|
|
263
|
+
const onScroll = React.useCallback((event) => {
|
|
264
|
+
const {
|
|
265
|
+
nativeEvent: {
|
|
266
|
+
contentOffset: { y },
|
|
267
|
+
layoutMeasurement: { height },
|
|
268
|
+
contentSize: { height: contentHeight },
|
|
269
|
+
},
|
|
270
|
+
} = event;
|
|
271
|
+
|
|
272
|
+
if (y >= 0 && y + height <= contentHeight) {
|
|
273
|
+
scrollY.setValue(y);
|
|
274
|
+
}
|
|
275
|
+
}, []);
|
|
276
|
+
|
|
196
277
|
if (shouldShowLoadingError) {
|
|
197
278
|
return <RiverError />;
|
|
198
279
|
}
|
|
@@ -208,6 +289,9 @@ function ComponentsMapComponent(props: Props) {
|
|
|
208
289
|
>
|
|
209
290
|
<ViewportTracker>
|
|
210
291
|
<FlatList
|
|
292
|
+
ref={(ref) => {
|
|
293
|
+
flatListRef.current = ref;
|
|
294
|
+
}}
|
|
211
295
|
// Fix for WebView rerender crashes on Android API 28+
|
|
212
296
|
// https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
|
|
213
297
|
overScrollMode={Platform.OS === "android" ? "never" : "auto"}
|
|
@@ -227,6 +311,11 @@ function ComponentsMapComponent(props: Props) {
|
|
|
227
311
|
}
|
|
228
312
|
ListFooterComponent={renderFooter}
|
|
229
313
|
refreshControl={refreshControl}
|
|
314
|
+
onScrollBeginDrag={onScrollBeginDrag}
|
|
315
|
+
onScroll={onScroll}
|
|
316
|
+
onMomentumScrollEnd={_onMomentumScrollEnd}
|
|
317
|
+
onScrollEndDrag={_onScrollEndDrag}
|
|
318
|
+
scrollEventThrottle={16}
|
|
230
319
|
{...scrollViewExtraProps}
|
|
231
320
|
/>
|
|
232
321
|
</ViewportTracker>
|