@applicaster/zapp-react-native-ui-components 15.0.0-alpha.3514407021 → 15.0.0-alpha.3752284136
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/AnimatedInOut/index.tsx +69 -26
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/Cell.tsx +8 -3
- package/Components/Cell/FocusableWrapper.tsx +3 -0
- package/Components/Cell/TvOSCellComponent.tsx +26 -5
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +14 -3
- package/Components/HandlePlayable/HandlePlayable.tsx +17 -65
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +74 -0
- package/Components/Layout/TV/LayoutBackground.tsx +5 -2
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +3 -4
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +10 -6
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
- package/Components/MasterCell/index.tsx +2 -0
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
- package/Components/MasterCell/utils/index.ts +61 -31
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
- package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +51 -55
- package/Components/PlayerContainer/useRestrictMobilePlayback.tsx +101 -0
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +65 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +2 -3
- package/Components/Screen/index.tsx +2 -3
- package/Components/Screen/navigationHandler.ts +49 -24
- package/Components/Screen/orientationHandler.ts +3 -3
- package/Components/ScreenResolver/index.tsx +13 -7
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/Tabs/TV/Tabs.tsx +20 -3
- package/Components/Transitioner/Scene.tsx +15 -2
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/VideoModal.tsx +1 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/Components/VideoModal/utils.ts +19 -9
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/index.d.ts +7 -0
- package/package.json +6 -5
- package/Components/River/TV/withTVEventHandler.tsx +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
- package/Helpers/DataSourceHelper/index.js +0 -19
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
TouchableWithoutFeedback,
|
|
9
9
|
} from "react-native";
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
12
12
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
13
13
|
import { textTransform } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
14
14
|
import { useNotificationHeight } from "../utils";
|
|
@@ -46,7 +46,7 @@ export const NotificationView = ({
|
|
|
46
46
|
online = true,
|
|
47
47
|
dismiss,
|
|
48
48
|
}: Props) => {
|
|
49
|
-
const
|
|
49
|
+
const plugins = usePlugins();
|
|
50
50
|
const { statusHeight, notificationHeight } = useNotificationHeight();
|
|
51
51
|
|
|
52
52
|
const offlinePlugin = R.find(
|
|
@@ -8,25 +8,24 @@ import {
|
|
|
8
8
|
offlinePhrase,
|
|
9
9
|
} from "../NotificationView";
|
|
10
10
|
|
|
11
|
-
jest.mock("@applicaster/zapp-react-native-redux
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
11
|
+
jest.mock("@applicaster/zapp-react-native-redux", () => ({
|
|
12
|
+
...jest.requireActual("@applicaster/zapp-react-native-redux"),
|
|
13
|
+
usePlugins: () => [
|
|
14
|
+
{
|
|
15
|
+
name: "offline experience",
|
|
16
|
+
identifier: "offline-experience",
|
|
17
|
+
type: "general",
|
|
18
|
+
module: {
|
|
19
|
+
useOfflineExperienceConfiguration: () => ({
|
|
20
|
+
configurationFields: {},
|
|
21
|
+
localizations: {
|
|
22
|
+
offline_toast_message: "No internet connection",
|
|
23
|
+
online_toast_message: "You are back online",
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
27
26
|
},
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
},
|
|
28
|
+
],
|
|
30
29
|
}));
|
|
31
30
|
|
|
32
31
|
jest.mock("react-native-safe-area-context", () => ({
|
|
@@ -8,36 +8,45 @@ const mockPreviousValue = null;
|
|
|
8
8
|
|
|
9
9
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => {
|
|
10
10
|
return {
|
|
11
|
+
...jest.requireActual(
|
|
12
|
+
"@applicaster/zapp-react-native-utils/reactHooks/connection"
|
|
13
|
+
),
|
|
11
14
|
useConnectionInfo: jest.fn(() => mockConnectionStatus),
|
|
12
15
|
};
|
|
13
16
|
});
|
|
14
17
|
|
|
15
18
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/utils", () => {
|
|
16
19
|
return {
|
|
20
|
+
...jest.requireActual(
|
|
21
|
+
"@applicaster/zapp-react-native-utils/reactHooks/utils"
|
|
22
|
+
),
|
|
17
23
|
usePrevious: jest.fn(() => mockPreviousValue),
|
|
18
24
|
};
|
|
19
25
|
});
|
|
20
26
|
|
|
27
|
+
const mock_storeObj = {
|
|
28
|
+
plugins: [
|
|
29
|
+
{
|
|
30
|
+
name: "offline experience",
|
|
31
|
+
identifier: "offline-experience",
|
|
32
|
+
type: "general",
|
|
33
|
+
module: {
|
|
34
|
+
useOfflineExperienceConfiguration: () => ({
|
|
35
|
+
configurationFields: {},
|
|
36
|
+
localizations: {
|
|
37
|
+
offline_toast_message: "No internet connection",
|
|
38
|
+
online_toast_message: "You are back online",
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
|
|
21
46
|
jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
22
47
|
...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{
|
|
26
|
-
name: "offline experience",
|
|
27
|
-
identifier: "offline-experience",
|
|
28
|
-
type: "general",
|
|
29
|
-
module: {
|
|
30
|
-
useOfflineExperienceConfiguration: () => ({
|
|
31
|
-
configurationFields: {},
|
|
32
|
-
localizations: {
|
|
33
|
-
offline_toast_message: "No internet connection",
|
|
34
|
-
online_toast_message: "You are back online",
|
|
35
|
-
},
|
|
36
|
-
}),
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
}),
|
|
48
|
+
usePlugins: () => mock_storeObj.plugins,
|
|
49
|
+
usePickFromState: () => ({}),
|
|
41
50
|
}));
|
|
42
51
|
|
|
43
52
|
jest.mock("react-native-safe-area-context", () => ({
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
|
|
18
18
|
import { TVEventHandlerComponent } from "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent";
|
|
19
19
|
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
import {
|
|
22
22
|
useBackHandler,
|
|
23
23
|
useNavigation,
|
|
@@ -56,15 +56,12 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
|
56
56
|
import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
|
|
57
57
|
import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
|
|
58
58
|
|
|
59
|
-
import {
|
|
60
|
-
PlayerAnimationStateEnum,
|
|
61
|
-
useModalAnimationContext,
|
|
62
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
63
|
-
|
|
64
59
|
import {
|
|
65
60
|
PlayerNativeCommandTypes,
|
|
66
61
|
PlayerNativeSendCommand,
|
|
67
62
|
} from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerNativeCommand";
|
|
63
|
+
import { useAppData } from "@applicaster/zapp-react-native-redux";
|
|
64
|
+
import { useRestrictMobilePlayback } from "./useRestrictMobilePlayback";
|
|
68
65
|
|
|
69
66
|
type Props = {
|
|
70
67
|
Player: React.ComponentType<any>;
|
|
@@ -243,14 +240,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
243
240
|
const [isLoadingNextVideo, setIsLoadingNextVideo] = React.useState(false);
|
|
244
241
|
|
|
245
242
|
const navigator = useNavigation();
|
|
246
|
-
const {
|
|
243
|
+
const { isTabletPortrait } = useAppData();
|
|
247
244
|
const prevItemId = usePrevious(item?.id);
|
|
248
245
|
const screenData = useTargetScreenData(item);
|
|
249
246
|
const { setVisible: showNavBar } = useSetNavbarState();
|
|
250
247
|
|
|
251
|
-
const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
|
|
252
|
-
useModalAnimationContext();
|
|
253
|
-
|
|
254
248
|
const playerEvent = (event, ...args) => {
|
|
255
249
|
playerManager.invokeHandler(event, ...args);
|
|
256
250
|
};
|
|
@@ -271,7 +265,21 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
271
265
|
|
|
272
266
|
showNavBar(true);
|
|
273
267
|
navigator.goBack();
|
|
274
|
-
}, [isModal,
|
|
268
|
+
}, [isModal, state.playerId, showNavBar, navigator]);
|
|
269
|
+
|
|
270
|
+
const pluginConfiguration = React.useMemo(() => {
|
|
271
|
+
return (
|
|
272
|
+
playerManager.getPluginConfiguration() ||
|
|
273
|
+
R.prop("__plugin_configuration", Player)
|
|
274
|
+
);
|
|
275
|
+
}, [playerManager.isRegistered()]);
|
|
276
|
+
|
|
277
|
+
const { isRestricted } = useRestrictMobilePlayback({
|
|
278
|
+
player,
|
|
279
|
+
entry: item,
|
|
280
|
+
pluginConfiguration,
|
|
281
|
+
close,
|
|
282
|
+
});
|
|
275
283
|
|
|
276
284
|
const playEntry = (entry) => navigator.replaceTop(entry, { mode });
|
|
277
285
|
|
|
@@ -463,13 +471,6 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
463
471
|
}
|
|
464
472
|
}, []);
|
|
465
473
|
|
|
466
|
-
const pluginConfiguration = React.useMemo(() => {
|
|
467
|
-
return (
|
|
468
|
-
playerManager.getPluginConfiguration() ||
|
|
469
|
-
R.prop("__plugin_configuration", Player)
|
|
470
|
-
);
|
|
471
|
-
}, [playerManager.isRegistered()]);
|
|
472
|
-
|
|
473
474
|
const disableMiniPlayer = React.useMemo(() => {
|
|
474
475
|
return pluginConfiguration?.disable_mini_player_when_inline;
|
|
475
476
|
}, [pluginConfiguration]);
|
|
@@ -482,8 +483,6 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
482
483
|
if (isModal && mode === VideoModalMode.MAXIMIZED) {
|
|
483
484
|
if (disableMiniPlayer) {
|
|
484
485
|
navigator.closeVideoModal();
|
|
485
|
-
} else {
|
|
486
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
487
486
|
}
|
|
488
487
|
}
|
|
489
488
|
|
|
@@ -671,41 +670,38 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
671
670
|
<PlayerFocusableWrapperView
|
|
672
671
|
nextFocusDown={context.bottomFocusableId}
|
|
673
672
|
>
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
navigator.isVideoModalDocked()
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
>
|
|
707
|
-
{renderApplePlayer(applePlayerProps)}
|
|
708
|
-
</Player>
|
|
673
|
+
{isRestricted ? null : (
|
|
674
|
+
<Player
|
|
675
|
+
source={{
|
|
676
|
+
uri,
|
|
677
|
+
entry: item,
|
|
678
|
+
}}
|
|
679
|
+
focused={isInlineTV ? true : undefined}
|
|
680
|
+
autoplay={true}
|
|
681
|
+
controls={false}
|
|
682
|
+
disableCastAction={disableCastAction}
|
|
683
|
+
docked={navigator.isVideoModalDocked()}
|
|
684
|
+
entry={item}
|
|
685
|
+
fullscreen={mode === VideoModalMode.FULLSCREEN}
|
|
686
|
+
inline={inline}
|
|
687
|
+
isModal={isModal}
|
|
688
|
+
isTabletPortrait={isTabletPortrait}
|
|
689
|
+
muted={false}
|
|
690
|
+
playableItem={item}
|
|
691
|
+
playerEvent={playerEvent}
|
|
692
|
+
playerId={state.playerId}
|
|
693
|
+
pluginConfiguration={pluginConfiguration}
|
|
694
|
+
ref={playerRef}
|
|
695
|
+
toggleFullscreen={toggleFullscreen}
|
|
696
|
+
style={videoStyle}
|
|
697
|
+
playNextData={playNextData}
|
|
698
|
+
setNextVideoPreloadThresholdPercentage={
|
|
699
|
+
setNextVideoPreloadThresholdPercentage
|
|
700
|
+
}
|
|
701
|
+
>
|
|
702
|
+
{renderApplePlayer(applePlayerProps)}
|
|
703
|
+
</Player>
|
|
704
|
+
)}
|
|
709
705
|
</PlayerFocusableWrapperView>
|
|
710
706
|
|
|
711
707
|
{state.error ? <ErrorDisplay error={state.error} /> : null}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
|
|
2
|
+
import NetInfo from "@react-native-community/netinfo";
|
|
3
|
+
|
|
4
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { showAlertDialog } from "@applicaster/zapp-react-native-utils/alertUtils";
|
|
6
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
7
|
+
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
8
|
+
import { log_info } from "./logger";
|
|
9
|
+
|
|
10
|
+
type RestrictMobilePlaybackProps = {
|
|
11
|
+
player?: Player;
|
|
12
|
+
entry?: ZappEntry;
|
|
13
|
+
pluginConfiguration?: Record<string, string>;
|
|
14
|
+
close: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const useRestrictMobilePlayback = ({
|
|
18
|
+
player,
|
|
19
|
+
entry,
|
|
20
|
+
pluginConfiguration,
|
|
21
|
+
close,
|
|
22
|
+
}: RestrictMobilePlaybackProps): { isRestricted: boolean } => {
|
|
23
|
+
const dialogVisibleRef = useRef<boolean>(false);
|
|
24
|
+
const theme = useTheme();
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
return () => {
|
|
28
|
+
if (isTV()) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dialogVisibleRef.current = false;
|
|
33
|
+
};
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
const isConnectionRestricted = useMemo(() => {
|
|
37
|
+
if (isTV()) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return player && entry?.extensions?.connection_restricted;
|
|
42
|
+
}, [player, entry]);
|
|
43
|
+
|
|
44
|
+
const [isRestricted, setIsRestricted] = useState<boolean>(
|
|
45
|
+
isConnectionRestricted
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!isConnectionRestricted) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const stopPlayer = () => {
|
|
54
|
+
log_info(
|
|
55
|
+
"Stopping player due to mobile restriction, connection_restricted: true"
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
player?.close();
|
|
59
|
+
|
|
60
|
+
dialogVisibleRef.current = true;
|
|
61
|
+
|
|
62
|
+
showAlertDialog({
|
|
63
|
+
title:
|
|
64
|
+
pluginConfiguration?.mobile_connection_restricted_alert_title ||
|
|
65
|
+
"Restricted Connection Type",
|
|
66
|
+
message:
|
|
67
|
+
pluginConfiguration?.mobile_connection_restricted_alert_message ||
|
|
68
|
+
"This content can only be viewed over a Wi-Fi or LAN network.",
|
|
69
|
+
okButtonText: theme.ok_button || "OK",
|
|
70
|
+
completion: () => {
|
|
71
|
+
dialogVisibleRef.current = false;
|
|
72
|
+
|
|
73
|
+
close();
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return NetInfo.addEventListener((state) => {
|
|
79
|
+
if (state.type === "cellular") {
|
|
80
|
+
setIsRestricted(true);
|
|
81
|
+
|
|
82
|
+
if (dialogVisibleRef.current) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
stopPlayer();
|
|
87
|
+
} else {
|
|
88
|
+
setIsRestricted(false);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}, [
|
|
92
|
+
close,
|
|
93
|
+
entry?.extensions?.connection_restricted,
|
|
94
|
+
pluginConfiguration,
|
|
95
|
+
player,
|
|
96
|
+
theme.ok_button,
|
|
97
|
+
isConnectionRestricted,
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
return { isRestricted };
|
|
101
|
+
};
|
|
@@ -2,12 +2,6 @@ import React, { PropsWithChildren } from "react";
|
|
|
2
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";
|
|
11
5
|
|
|
12
6
|
type Props = PropsWithChildren<{
|
|
13
7
|
entry: ZappEntry;
|
|
@@ -25,30 +19,17 @@ const PlayerImageBackgroundComponent = ({
|
|
|
25
19
|
style,
|
|
26
20
|
imageStyle,
|
|
27
21
|
imageKey,
|
|
28
|
-
defaultImageDimensions,
|
|
29
22
|
}: Props) => {
|
|
30
23
|
const source = React.useMemo(
|
|
31
24
|
() => ({ uri: imageSrcFromMediaItem(entry, [imageKey]) }),
|
|
32
25
|
[imageKey, entry]
|
|
33
26
|
);
|
|
34
27
|
|
|
35
|
-
const { playerAnimationState } = useModalAnimationContext();
|
|
36
|
-
|
|
37
28
|
if (!source) return <>{children}</>;
|
|
38
29
|
|
|
39
30
|
return (
|
|
40
|
-
<View
|
|
41
|
-
style={
|
|
42
|
-
playerAnimationState === PlayerAnimationStateEnum.maximize
|
|
43
|
-
? defaultImageDimensions
|
|
44
|
-
: style
|
|
45
|
-
}
|
|
46
|
-
>
|
|
47
|
-
<AnimationComponent
|
|
48
|
-
style={style}
|
|
49
|
-
animationType={ComponentAnimationType.player}
|
|
50
|
-
additionalData={defaultImageDimensions}
|
|
51
|
-
>
|
|
31
|
+
<View style={style}>
|
|
32
|
+
<View style={style}>
|
|
52
33
|
<ImageBackground
|
|
53
34
|
resizeMode="cover"
|
|
54
35
|
style={imageSize}
|
|
@@ -57,7 +38,7 @@ const PlayerImageBackgroundComponent = ({
|
|
|
57
38
|
>
|
|
58
39
|
{children}
|
|
59
40
|
</ImageBackground>
|
|
60
|
-
</
|
|
41
|
+
</View>
|
|
61
42
|
</View>
|
|
62
43
|
);
|
|
63
44
|
};
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Text } from "react-native";
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
import { mergeRight } from "@applicaster/zapp-react-native-utils/utils";
|
|
6
7
|
|
|
7
8
|
import { GeneralContentScreen } from "../../GeneralContentScreen";
|
|
8
9
|
import { ScreenResolver } from "@applicaster/zapp-react-native-ui-components/Components/ScreenResolver";
|
|
@@ -13,6 +14,8 @@ import {
|
|
|
13
14
|
} from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
14
15
|
import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks/state";
|
|
15
16
|
|
|
17
|
+
import { toStringOrEmpty } from "./utils";
|
|
18
|
+
|
|
16
19
|
type Props = {
|
|
17
20
|
screenId: string;
|
|
18
21
|
screenData: ZappRiver | ZappEntry;
|
|
@@ -24,6 +27,7 @@ type Props = {
|
|
|
24
27
|
isInsideContainer?: boolean;
|
|
25
28
|
extraAnchorPointYOffset: number;
|
|
26
29
|
river?: ZappRiver | ZappEntry;
|
|
30
|
+
groupId: string;
|
|
27
31
|
};
|
|
28
32
|
|
|
29
33
|
export const River = (props: Props) => {
|
|
@@ -35,6 +39,7 @@ export const River = (props: Props) => {
|
|
|
35
39
|
componentsMapExtraProps,
|
|
36
40
|
isInsideContainer,
|
|
37
41
|
extraAnchorPointYOffset,
|
|
42
|
+
groupId,
|
|
38
43
|
} = props;
|
|
39
44
|
|
|
40
45
|
const { title: screenTitle, summary: screenSummary } = useNavbarState();
|
|
@@ -51,28 +56,41 @@ export const River = (props: Props) => {
|
|
|
51
56
|
[screenId]
|
|
52
57
|
);
|
|
53
58
|
|
|
54
|
-
const
|
|
55
|
-
|
|
59
|
+
const screenResolverData = React.useMemo(() => {
|
|
60
|
+
const extraData = mergeRight(extraProps, screenResolverExtraProps);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
extraData,
|
|
64
|
+
screenData: mergeRight(river, { groupId: extraData?.groupId }),
|
|
65
|
+
componentsMapExtraProps: mergeRight(componentsMapExtraProps, { groupId }),
|
|
66
|
+
};
|
|
67
|
+
}, [
|
|
68
|
+
extraProps,
|
|
69
|
+
screenResolverExtraProps,
|
|
70
|
+
river,
|
|
71
|
+
componentsMapExtraProps,
|
|
72
|
+
groupId,
|
|
73
|
+
]);
|
|
56
74
|
|
|
57
75
|
React.useEffect(() => {
|
|
58
76
|
if (!isInsideContainer) {
|
|
59
|
-
setScreenTitle(
|
|
60
|
-
setScreenSummary(
|
|
77
|
+
setScreenTitle(toStringOrEmpty(screenData?.title));
|
|
78
|
+
setScreenSummary(toStringOrEmpty(screenData?.summary));
|
|
61
79
|
}
|
|
62
80
|
}, [screenData.id]);
|
|
63
81
|
|
|
64
82
|
React.useEffect(() => {
|
|
65
83
|
if (feedData && !isInsideContainer) {
|
|
66
84
|
if (feedData.title && feedData.title !== screenTitle) {
|
|
67
|
-
setScreenTitle(
|
|
85
|
+
setScreenTitle(toStringOrEmpty(feedData.title));
|
|
68
86
|
}
|
|
69
87
|
|
|
70
88
|
if (feedData.summary && feedData.summary !== screenSummary) {
|
|
71
|
-
setScreenSummary(
|
|
89
|
+
setScreenSummary(toStringOrEmpty(feedData.summary));
|
|
72
90
|
}
|
|
73
91
|
} else {
|
|
74
|
-
setScreenTitle(
|
|
75
|
-
setScreenSummary(
|
|
92
|
+
setScreenTitle(toStringOrEmpty(screenData?.title));
|
|
93
|
+
setScreenSummary(toStringOrEmpty(screenData?.summary));
|
|
76
94
|
}
|
|
77
95
|
}, [feedData, screenData, screenTitle, screenSummary]);
|
|
78
96
|
|
|
@@ -86,15 +104,13 @@ export const River = (props: Props) => {
|
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
if (river.type !== "general_content") {
|
|
89
|
-
const extraData = { ...R.mergeRight(extraProps, screenResolverExtraProps) };
|
|
90
|
-
|
|
91
107
|
return (
|
|
92
108
|
<ScreenResolver
|
|
93
109
|
screenType={river.type}
|
|
94
110
|
screenId={screenId}
|
|
95
|
-
screenData={
|
|
96
|
-
componentsMapExtraProps={componentsMapExtraProps}
|
|
97
|
-
{...extraData}
|
|
111
|
+
screenData={screenResolverData.screenData}
|
|
112
|
+
componentsMapExtraProps={screenResolverData.componentsMapExtraProps}
|
|
113
|
+
{...screenResolverData.extraData}
|
|
98
114
|
/>
|
|
99
115
|
);
|
|
100
116
|
}
|
|
@@ -106,6 +122,7 @@ export const River = (props: Props) => {
|
|
|
106
122
|
isScreenWrappedInContainer={isInsideContainer}
|
|
107
123
|
extraAnchorPointYOffset={extraAnchorPointYOffset}
|
|
108
124
|
componentsMapExtraProps={componentsMapExtraProps}
|
|
125
|
+
groupId={groupId}
|
|
109
126
|
/>
|
|
110
127
|
);
|
|
111
128
|
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { compose } from "
|
|
1
|
+
import { compose, identity } from "@applicaster/zapp-react-native-utils/utils";
|
|
2
|
+
import { isTvOSPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
+
|
|
2
4
|
import { River as RiverComponent } from "./River";
|
|
3
|
-
import { withTvEventHandler } from "./withTVEventHandler";
|
|
4
5
|
import { withComponentsMapOffsetContext } from "../../../Contexts/ComponentsMapOffsetContext";
|
|
5
6
|
import { withRiverDataLoader } from "./withRiverDataLoader";
|
|
7
|
+
import { withFocusableGroupForContent } from "./withFocusableGroupForContent";
|
|
8
|
+
|
|
9
|
+
const isTVOS = isTvOSPlatform();
|
|
6
10
|
|
|
7
11
|
export const River = compose(
|
|
8
|
-
withTvEventHandler,
|
|
9
12
|
withComponentsMapOffsetContext,
|
|
10
|
-
withRiverDataLoader
|
|
13
|
+
withRiverDataLoader,
|
|
14
|
+
isTVOS ? withFocusableGroupForContent : identity
|
|
11
15
|
)(RiverComponent);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { toStringOrEmpty } from "..";
|
|
2
|
+
|
|
3
|
+
describe("toStringOrEmpty", () => {
|
|
4
|
+
test("returns empty string for undefined", () => {
|
|
5
|
+
expect(toStringOrEmpty(undefined)).toBe("");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("returns empty string for null", () => {
|
|
9
|
+
expect(toStringOrEmpty(null)).toBe("");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("converts number to string", () => {
|
|
13
|
+
expect(toStringOrEmpty(0)).toBe("0");
|
|
14
|
+
expect(toStringOrEmpty(123)).toBe("123");
|
|
15
|
+
expect(toStringOrEmpty(-42)).toBe("-42");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("returns string as is", () => {
|
|
19
|
+
expect(toStringOrEmpty("hello")).toBe("hello");
|
|
20
|
+
expect(toStringOrEmpty("")).toBe("");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("works with numeric strings", () => {
|
|
24
|
+
expect(toStringOrEmpty("123")).toBe("123");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("does not throw on falsy values like 0", () => {
|
|
28
|
+
expect(toStringOrEmpty(0)).toBe("0");
|
|
29
|
+
});
|
|
30
|
+
});
|