@applicaster/zapp-react-native-ui-components 12.0.0-alpha.5353184830 → 12.0.0-alpha.5400461972
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 +28 -41
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- 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/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/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- 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 +97 -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 +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +103 -102
- 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/ScreenResolver/index.tsx +1 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +9 -2
- 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 +45 -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 +82 -50
- package/Components/VideoModal/VideoModal.tsx +25 -42
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +12 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/utils.ts +3 -3
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- 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/Contexts/ScreenDataContext/index.ts +3 -0
- 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
|
@@ -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
|
+
};
|
|
@@ -12,19 +12,7 @@ jest.mock("@applicaster/quick-brick-core/App/ActionSetters", () => ({
|
|
|
12
12
|
useRiverInitialState: () => ({}),
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
|
-
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen"
|
|
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
|
-
}));
|
|
15
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen");
|
|
28
16
|
|
|
29
17
|
const Layout = require("..").default;
|
|
30
18
|
|
|
@@ -125,25 +113,4 @@ describe("Layout TV", () => {
|
|
|
125
113
|
expect(bgComponent.props.testProp).toBe(true);
|
|
126
114
|
});
|
|
127
115
|
});
|
|
128
|
-
|
|
129
|
-
describe("props passed to navbar component", () => {
|
|
130
|
-
it("passes correct props", () => {
|
|
131
|
-
const { getByTestId } = render(
|
|
132
|
-
<Layout
|
|
133
|
-
Components={Components}
|
|
134
|
-
ComponentsExtraProps={{
|
|
135
|
-
NavBar: { testProp: true },
|
|
136
|
-
}}
|
|
137
|
-
>
|
|
138
|
-
<Screen />
|
|
139
|
-
</Layout>,
|
|
140
|
-
{ wrapper }
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const navbarComponent = getByTestId("nav-bar-component");
|
|
144
|
-
expect(navbarComponent.props.isVisible).toBe(isNavBarVisible);
|
|
145
|
-
expect(navbarComponent.props.menuPlugin).toBe(plugins[0]);
|
|
146
|
-
expect(navbarComponent.props.testProp).toBe(true);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
116
|
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
|
-
import {
|
|
5
|
-
useIsNavBarVisible,
|
|
6
|
-
useNavigation,
|
|
7
|
-
} from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
4
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
8
5
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
9
6
|
|
|
10
7
|
import {
|
|
@@ -23,6 +20,7 @@ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
|
|
|
23
20
|
import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
24
21
|
import { PathnameContext } from "../../../Contexts/PathnameContext";
|
|
25
22
|
import { useNavbarState } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
23
|
+
import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
|
|
26
24
|
|
|
27
25
|
type Components = {
|
|
28
26
|
NavBar: React.ComponentType<any>;
|
|
@@ -43,7 +41,7 @@ type Props = {
|
|
|
43
41
|
const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
44
42
|
const navigator = useNavigation();
|
|
45
43
|
const theme = useTheme();
|
|
46
|
-
const { title } = useNavbarState();
|
|
44
|
+
const { title, visible } = useNavbarState();
|
|
47
45
|
const { activeRiver, currentRoute } = navigator;
|
|
48
46
|
|
|
49
47
|
const {
|
|
@@ -80,10 +78,22 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
80
78
|
[]
|
|
81
79
|
);
|
|
82
80
|
|
|
83
|
-
const navBarVisible = useIsNavBarVisible();
|
|
84
|
-
|
|
85
81
|
const [navBarReady, setNavBarReady] = React.useState(false);
|
|
86
82
|
|
|
83
|
+
const navBarContainer = (
|
|
84
|
+
<NavBarContainer isVisible={visible} onReady={setNavBarReady}>
|
|
85
|
+
<NavBar
|
|
86
|
+
ref={ComponentsExtraProps?.NavBar?.ref}
|
|
87
|
+
isVisible={visible && !routeIsPlayerScreen(currentRoute)}
|
|
88
|
+
menuPlugin={menuPlugin}
|
|
89
|
+
navigationProps={navigationProps}
|
|
90
|
+
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
91
|
+
/>
|
|
92
|
+
</NavBarContainer>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const isTVOS = isApplePlatform();
|
|
96
|
+
|
|
87
97
|
if (!appReady) {
|
|
88
98
|
return null;
|
|
89
99
|
}
|
|
@@ -96,45 +106,22 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
96
106
|
backgroundImageUrl={backgroundImageUrl}
|
|
97
107
|
{...R.omit(["ref"])(ComponentsExtraProps?.Background)}
|
|
98
108
|
>
|
|
99
|
-
{
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
menuPlugin={menuPlugin}
|
|
105
|
-
navigationProps={navigationProps}
|
|
106
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
107
|
-
/>
|
|
108
|
-
</NavBarContainer>
|
|
109
|
-
) : null}
|
|
110
|
-
|
|
111
|
-
{navBarReady ? (
|
|
112
|
-
/**
|
|
109
|
+
<ScreenDataContext.Provider value={navigator.data}>
|
|
110
|
+
<PathnameContext.Provider value={navigator.currentRoute}>
|
|
111
|
+
{!isTVOS ? navBarContainer : null}
|
|
112
|
+
{navBarReady ? (
|
|
113
|
+
/**
|
|
113
114
|
Need to re-mount this component on each navigation event
|
|
114
115
|
It's a hack to work around the fact that we don't support
|
|
115
116
|
correct screen rendering in our navigator (shared currentRoute state)
|
|
116
117
|
**/
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
<ScreenContainer>{children}</ScreenContainer>
|
|
119
|
+
) : null}
|
|
120
|
+
{/** Render NavBarContainer over ScreenContainer to let tvOS native
|
|
121
|
+
focus manager works correctly to focus nav bar items first **/}
|
|
122
|
+
{isTVOS ? navBarContainer : null}
|
|
119
123
|
</PathnameContext.Provider>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
{isApplePlatform() ? (
|
|
123
|
-
/**
|
|
124
|
-
Render NavBarContainer over ScreenContainer to let tvOS native
|
|
125
|
-
focus manager works correctly to focus nav bar items first
|
|
126
|
-
**/
|
|
127
|
-
<NavBarContainer isVisible={navBarVisible} onReady={setNavBarReady}>
|
|
128
|
-
<NavBar
|
|
129
|
-
ref={ComponentsExtraProps?.NavBar?.ref}
|
|
130
|
-
isVisible={navBarVisible && !routeIsPlayerScreen(currentRoute)}
|
|
131
|
-
menuPlugin={menuPlugin}
|
|
132
|
-
navigationProps={navigationProps}
|
|
133
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
|
|
134
|
-
/>
|
|
135
|
-
</NavBarContainer>
|
|
136
|
-
) : null}
|
|
137
|
-
|
|
124
|
+
</ScreenDataContext.Provider>
|
|
138
125
|
<TransitionOverlay />
|
|
139
126
|
</Components.Background>
|
|
140
127
|
</ScreenLayoutContextProvider>
|
|
@@ -25,6 +25,7 @@ type Props = {
|
|
|
25
25
|
testID?: string;
|
|
26
26
|
accessibilityLabel?: string;
|
|
27
27
|
cellUUID?: string;
|
|
28
|
+
extraProps?: Record<string, any>;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
function isStringAsset(asset) {
|
|
@@ -108,6 +109,7 @@ export function ActionButton(props: Props) {
|
|
|
108
109
|
flavour={flavour}
|
|
109
110
|
asset={getAssetValue(asset, flavour)}
|
|
110
111
|
cellUUID={cellUUID}
|
|
112
|
+
{...(props?.extraProps ?? {})}
|
|
111
113
|
/>
|
|
112
114
|
)}
|
|
113
115
|
</TouchableOpacity>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compact,
|
|
3
3
|
ifElseFocusedSelected,
|
|
4
|
+
ifElseSelected,
|
|
4
5
|
} from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
5
6
|
|
|
6
7
|
import { getPositionStyles } from "./utils";
|
|
@@ -12,9 +13,15 @@ type Props = {
|
|
|
12
13
|
value: Function;
|
|
13
14
|
state: string;
|
|
14
15
|
visible?: Boolean;
|
|
16
|
+
isMobile?: Boolean;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
export const CellBadge = ({
|
|
19
|
+
export const CellBadge = ({
|
|
20
|
+
value,
|
|
21
|
+
state,
|
|
22
|
+
visible = true,
|
|
23
|
+
isMobile = false,
|
|
24
|
+
}: Props) => {
|
|
18
25
|
if (!value("cell_badge_switch") || !visible) {
|
|
19
26
|
return null;
|
|
20
27
|
}
|
|
@@ -45,13 +52,19 @@ export const CellBadge = ({ value, state, visible = true }: Props) => {
|
|
|
45
52
|
data: [
|
|
46
53
|
{
|
|
47
54
|
func: () => {
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
return isMobile
|
|
56
|
+
? ifElseSelected(
|
|
57
|
+
state,
|
|
58
|
+
value("cell_badge_selected"),
|
|
59
|
+
value("cell_badge_default")
|
|
60
|
+
)
|
|
61
|
+
: ifElseFocusedSelected(
|
|
62
|
+
state,
|
|
63
|
+
value("cell_badge_focused"),
|
|
64
|
+
value("cell_badge_selected"),
|
|
65
|
+
value("cell_badge_focused_selected"),
|
|
66
|
+
value("cell_badge_default")
|
|
67
|
+
);
|
|
55
68
|
},
|
|
56
69
|
args: [],
|
|
57
70
|
propName: "uri",
|
|
@@ -4,6 +4,7 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
|
|
|
4
4
|
|
|
5
5
|
type DynamicBadgeProps = {
|
|
6
6
|
cellUUID?: string;
|
|
7
|
+
uri?: string;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
@@ -12,11 +13,12 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
|
12
13
|
// TODO: Initial value should depends on player state (playing or not)
|
|
13
14
|
const [showImage, setShowImage] = React.useState(true);
|
|
14
15
|
const player = usePlayer(playerId);
|
|
16
|
+
const uri = props?.uri;
|
|
15
17
|
|
|
16
18
|
React.useEffect(() => {
|
|
17
19
|
if (playerId && player) {
|
|
18
20
|
return player.addListener({
|
|
19
|
-
id:
|
|
21
|
+
id: `dynamic-badges-${uri}`,
|
|
20
22
|
listener: {
|
|
21
23
|
onPlayerClose: () => {
|
|
22
24
|
setShowImage(true);
|
|
@@ -35,7 +37,7 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
|
|
|
35
37
|
} else {
|
|
36
38
|
setShowImage(true);
|
|
37
39
|
}
|
|
38
|
-
}, [player]);
|
|
40
|
+
}, [player, uri]);
|
|
39
41
|
|
|
40
42
|
if (!showImage) {
|
|
41
43
|
return null;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { ImageStyle, View } from "react-native";
|
|
3
3
|
import * as R from "ramda";
|
|
4
|
-
import
|
|
4
|
+
import { QBImage } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
5
5
|
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
6
|
-
import { toFiniteNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
7
6
|
|
|
8
7
|
import { useImageSourceWithDefault, useCheckFailedUri } from "./hooks";
|
|
8
|
+
import useImageSize from "./hooks/useImageSize";
|
|
9
9
|
|
|
10
10
|
type Source = {
|
|
11
11
|
uri: string;
|
|
@@ -19,32 +19,13 @@ type Props = Record<string, any> & {
|
|
|
19
19
|
withDimensions: (source: Source) => Source;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const MemoizedImage = React.memo(
|
|
23
|
-
|
|
24
|
-
const normalize = Math.ceil;
|
|
22
|
+
const MemoizedImage = React.memo(QBImage, R.equals);
|
|
25
23
|
|
|
26
24
|
const isValidExternalSource = (source): boolean =>
|
|
27
25
|
source?.uri?.startsWith("http") ||
|
|
28
26
|
source?.uri?.startsWith("data:image") ||
|
|
29
27
|
source?.uri?.startsWith("file://");
|
|
30
28
|
|
|
31
|
-
const isValidSize = (size: unknown): boolean =>
|
|
32
|
-
toFiniteNumberWithDefault(0, size) > 0;
|
|
33
|
-
|
|
34
|
-
const getSourceWithMaxSizes = (applyMaxSize, style, source) => {
|
|
35
|
-
const { width, height } = style;
|
|
36
|
-
|
|
37
|
-
if (!applyMaxSize || !isValidSize(width) || !isValidSize(height)) {
|
|
38
|
-
return source;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
...source,
|
|
43
|
-
maxWidth: normalize(width),
|
|
44
|
-
maxHeight: normalize(height),
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
|
|
48
29
|
export default function Image({
|
|
49
30
|
style,
|
|
50
31
|
uri,
|
|
@@ -82,10 +63,12 @@ export default function Image({
|
|
|
82
63
|
|
|
83
64
|
const applyMaxSize = toBooleanWithDefaultFalse(otherProps?.applyMaxSize);
|
|
84
65
|
|
|
85
|
-
const sourceWithMaxSizes =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
66
|
+
const sourceWithMaxSizes = useImageSize({
|
|
67
|
+
style,
|
|
68
|
+
applyMaxSize,
|
|
69
|
+
source,
|
|
70
|
+
withDimensions,
|
|
71
|
+
});
|
|
89
72
|
|
|
90
73
|
if (isFailedToLoadUri(uri) || !isValidExternalSource(source)) {
|
|
91
74
|
return <View style={style} />;
|
|
@@ -43,14 +43,16 @@ function Image({
|
|
|
43
43
|
[source, error]
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
+
const _source = shouldRenderImg
|
|
47
|
+
? withDimensions(source)
|
|
48
|
+
: defaultPlaceHolderImage;
|
|
49
|
+
|
|
46
50
|
return (
|
|
47
51
|
// @ts-ignore
|
|
48
52
|
<MemoizedImage
|
|
49
53
|
style={style as ImageStyle}
|
|
50
54
|
onError={() => setErrorState(true)}
|
|
51
|
-
source={
|
|
52
|
-
shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
|
|
53
|
-
}
|
|
55
|
+
source={_source?.uri ? _source : undefined}
|
|
54
56
|
{...R.omit(["source"], otherProps)}
|
|
55
57
|
/>
|
|
56
58
|
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ImageStyle } from "react-native";
|
|
3
|
+
import { toFiniteNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
4
|
+
|
|
5
|
+
type Source = {
|
|
6
|
+
uri: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type Props = Record<string, any> & {
|
|
10
|
+
style: ImageStyle;
|
|
11
|
+
uri?: string;
|
|
12
|
+
placeholderImage?: string;
|
|
13
|
+
entry?: ZappEntry | ZappFeed;
|
|
14
|
+
withDimensions: (source: Source) => Source;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const normalize = Math.ceil;
|
|
18
|
+
|
|
19
|
+
const isValidSize = (size: unknown): boolean =>
|
|
20
|
+
toFiniteNumberWithDefault(0, size) > 0;
|
|
21
|
+
|
|
22
|
+
type WidthDimensions = { aspectRatio?: number; width: number; height?: number };
|
|
23
|
+
type HeightDimensions = {
|
|
24
|
+
aspectRatio?: number;
|
|
25
|
+
width?: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
type FullDimensions = { aspectRatio?: number; width: number; height: number };
|
|
29
|
+
type Dimensions = WidthDimensions | HeightDimensions | FullDimensions;
|
|
30
|
+
|
|
31
|
+
const calculateDimensions = ({ aspectRatio, width, height }: Dimensions) => {
|
|
32
|
+
if (aspectRatio) {
|
|
33
|
+
return {
|
|
34
|
+
width: width || height * aspectRatio,
|
|
35
|
+
height: height || width / aspectRatio,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return { width, height };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getSourceWithMaxSizes = (applyMaxSize, style, source) => {
|
|
43
|
+
const { width, height } = calculateDimensions(style);
|
|
44
|
+
|
|
45
|
+
if (!applyMaxSize || !isValidSize(width) || !isValidSize(height)) {
|
|
46
|
+
return source;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
...source,
|
|
51
|
+
maxWidth: normalize(width),
|
|
52
|
+
maxHeight: normalize(height),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default function useImageSize(props: Props) {
|
|
57
|
+
const { style, applyMaxSize, source, withDimensions } = props;
|
|
58
|
+
|
|
59
|
+
const sourceWithMaxSizes = React.useMemo(
|
|
60
|
+
() => withDimensions(getSourceWithMaxSizes(applyMaxSize, style, source)),
|
|
61
|
+
[applyMaxSize, style?.height, style?.width, source?.uri, withDimensions]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return sourceWithMaxSizes;
|
|
65
|
+
}
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { isVideoPreviewEnabled } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/utils";
|
|
3
3
|
import { LiveImage } from "../LiveImage";
|
|
4
4
|
import PureImage from "../Image";
|
|
5
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
6
|
|
|
6
7
|
type Props = {
|
|
7
8
|
enable_video_preview: boolean;
|
|
@@ -9,7 +10,10 @@ type Props = {
|
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export const ImageContainer = (props: Props) => {
|
|
12
|
-
const
|
|
13
|
+
const isActive = useIsScreenActive();
|
|
14
|
+
|
|
15
|
+
const Component =
|
|
16
|
+
isVideoPreviewEnabled(props) && isActive ? LiveImage : PureImage;
|
|
13
17
|
|
|
14
18
|
return <Component {...props} />;
|
|
15
19
|
};
|
|
@@ -18,6 +18,7 @@ type LiveImageProps = {
|
|
|
18
18
|
imageKey?: string;
|
|
19
19
|
state: "focused" | "unfocused" | "selected";
|
|
20
20
|
audio_muted_by_default?: boolean;
|
|
21
|
+
uri: string; // cover image url
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const DEFAULT_PLAYER_IDENTIFIER = "QuickBrickPlayerPlugin";
|
|
@@ -176,10 +177,23 @@ const getPlayerConfig = (player_screen_id, actionIdentifier) => {
|
|
|
176
177
|
const positionAbsolute: ViewStyle = { position: "absolute" };
|
|
177
178
|
|
|
178
179
|
const LiveImageComponent = (props: LiveImageProps) => {
|
|
179
|
-
const {
|
|
180
|
+
const {
|
|
181
|
+
item,
|
|
182
|
+
style: componentStyle,
|
|
183
|
+
cellUUID,
|
|
184
|
+
imageKey,
|
|
185
|
+
actionIdentifier,
|
|
186
|
+
state,
|
|
187
|
+
} = props;
|
|
180
188
|
|
|
181
189
|
const component = useUIComponentContext();
|
|
182
190
|
|
|
191
|
+
// Fix for blinking on state change
|
|
192
|
+
const style = React.useMemo(
|
|
193
|
+
() => ({ ...componentStyle, backgroundColor: "transparent" }),
|
|
194
|
+
[componentStyle]
|
|
195
|
+
);
|
|
196
|
+
|
|
183
197
|
const componentType = React.useMemo(
|
|
184
198
|
() => getPropComponentType(component),
|
|
185
199
|
[component?.id]
|
|
@@ -209,10 +223,11 @@ const LiveImageComponent = (props: LiveImageProps) => {
|
|
|
209
223
|
|
|
210
224
|
return (
|
|
211
225
|
<>
|
|
212
|
-
<Image {...props} />
|
|
226
|
+
<Image {...props} applyMaxSize />
|
|
213
227
|
{isShouldRender && (
|
|
214
228
|
<View style={[style, positionAbsolute]}>
|
|
215
229
|
<PlayerLiveImage
|
|
230
|
+
uri={props.uri}
|
|
216
231
|
playerId={cellUUID}
|
|
217
232
|
playerPluginId={playerPluginId}
|
|
218
233
|
screenConfig={screenConfig}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { isNil } from "ramda";
|
|
3
|
-
import {
|
|
3
|
+
import { ImageStyle, View } from "react-native";
|
|
4
4
|
import {
|
|
5
5
|
FIT_POSITION,
|
|
6
6
|
IMAGE_SIZING_FIT,
|
|
7
7
|
IMAGE_SIZING_FILL,
|
|
8
8
|
} from "@applicaster/zapp-react-native-utils/manifestUtils/secondaryImage";
|
|
9
|
+
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
9
10
|
|
|
10
11
|
import { useGetImageDimensions } from "./hooks";
|
|
11
12
|
import {
|
|
@@ -59,7 +60,7 @@ const SecondaryImageComponent = (props: Props) => {
|
|
|
59
60
|
|
|
60
61
|
return (
|
|
61
62
|
<View style={style} onLayout={onAsyncRender}>
|
|
62
|
-
<
|
|
63
|
+
<Image
|
|
63
64
|
{...props}
|
|
64
65
|
source={{ uri }}
|
|
65
66
|
style={{
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Text } from "react-native";
|
|
3
3
|
import { omit } from "ramda";
|
|
4
|
-
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
5
4
|
import {
|
|
6
5
|
textTransform,
|
|
7
6
|
dateFormat,
|
|
@@ -9,6 +8,9 @@ import {
|
|
|
9
8
|
|
|
10
9
|
import { useTextLabel, withFocusedStyles } from "./hooks";
|
|
11
10
|
import { withScaledLineHeight } from "./utils";
|
|
11
|
+
import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
12
|
+
import { MeasurementPortalContext } from "../../../MeasurmentsPortal";
|
|
13
|
+
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
12
14
|
|
|
13
15
|
type Props = {
|
|
14
16
|
style: any;
|
|
@@ -32,14 +34,24 @@ const _Text = ({
|
|
|
32
34
|
...otherProps
|
|
33
35
|
}: Props) => {
|
|
34
36
|
const _label = useTextLabel({ label, entry });
|
|
37
|
+
const isMeasurement = React.useContext(MeasurementPortalContext);
|
|
35
38
|
|
|
36
39
|
if (isNilOrEmpty(_label)) {
|
|
37
40
|
return null;
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
// set maximum possible height for the text in case of measurement
|
|
44
|
+
const height =
|
|
45
|
+
isMeasurement && otherProps.numberOfLines && style.lineHeight
|
|
46
|
+
? toNumber(otherProps.numberOfLines) * toNumber(style.lineHeight)
|
|
47
|
+
: undefined;
|
|
48
|
+
|
|
40
49
|
return (
|
|
41
50
|
<Text
|
|
42
|
-
style={
|
|
51
|
+
style={[
|
|
52
|
+
withScaledLineHeight(withFocusedStyles({ style, otherProps })),
|
|
53
|
+
{ height },
|
|
54
|
+
]}
|
|
43
55
|
{...withoutLabel(otherProps)}
|
|
44
56
|
>
|
|
45
57
|
{dateTransformEnabled
|
|
@@ -23,7 +23,11 @@ export const Toggle = (props: Props) => {
|
|
|
23
23
|
iosBackgroundColor,
|
|
24
24
|
} = style;
|
|
25
25
|
|
|
26
|
-
const isSelected = React.useMemo(
|
|
26
|
+
const isSelected = React.useMemo(
|
|
27
|
+
() => cellState === "selected",
|
|
28
|
+
[item?.id, cellState]
|
|
29
|
+
);
|
|
30
|
+
|
|
27
31
|
const actionContext = useActions(action?.identifier);
|
|
28
32
|
|
|
29
33
|
const [actionState, setActionState] = useState(
|