@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3977160850 → 12.0.0-alpha.4337072244

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.
Files changed (82) hide show
  1. package/Components/BaseFocusable/index.tsx +1 -1
  2. package/Components/Cell/Cell.tsx +7 -7
  3. package/Components/Cell/CellWithFocusable.tsx +38 -19
  4. package/Components/Cell/TvOSCellComponent.tsx +2 -2
  5. package/Components/ErrorScreen/index.tsx +1 -1
  6. package/Components/FocusableCell/index.tsx +7 -7
  7. package/Components/FocusableGroup/index.tsx +1 -0
  8. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  9. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  10. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  11. package/Components/HookRenderer/index.tsx +1 -3
  12. package/Components/Image/Image.android.tsx +3 -25
  13. package/Components/Image/Image.tsx +18 -2
  14. package/Components/Image/utils/index.ts +39 -0
  15. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  16. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -10
  17. package/Components/Layout/TV/__tests__/index.test.tsx +18 -86
  18. package/Components/Layout/TV/index.tsx +43 -102
  19. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  20. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
  21. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  22. package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
  23. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  24. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +17 -2
  25. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
  26. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  27. package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
  28. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  29. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  30. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  31. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
  32. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  33. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  34. package/Components/MasterCell/utils/index.ts +18 -7
  35. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  36. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  37. package/Components/PlayerContainer/PlayerContainer.tsx +64 -31
  38. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
  39. package/Components/PlayerImageBackground/index.tsx +34 -8
  40. package/Components/River/ComponentsMap/ComponentsMap.tsx +86 -22
  41. package/Components/River/RefreshControl.tsx +55 -1
  42. package/Components/River/TV/River.tsx +0 -23
  43. package/Components/River/__tests__/componentsMap.test.js +7 -0
  44. package/Components/RouteManager/index.tsx +2 -2
  45. package/Components/Screen/TV/hooks/index.ts +3 -0
  46. package/Components/Screen/TV/hooks/useInitialFocus.ts +67 -0
  47. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  48. package/Components/Screen/TV/index.web.tsx +174 -0
  49. package/Components/Screen/__tests__/Screen.test.tsx +5 -1
  50. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +14 -0
  51. package/Components/Screen/index.tsx +48 -28
  52. package/Components/ScreenResolver/index.tsx +3 -1
  53. package/Components/Tabs/TV/styles.ts +1 -1
  54. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -28
  55. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
  56. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
  57. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  58. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
  59. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
  60. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
  61. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
  62. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  63. package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
  64. package/Components/VideoModal/PlayerWrapper.tsx +66 -43
  65. package/Components/VideoModal/VideoModal.tsx +25 -42
  66. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +6 -1
  67. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
  68. package/Components/VideoModal/utils.ts +3 -3
  69. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +1 -1
  70. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  71. package/Components/Viewport/utils.js +1 -1
  72. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  73. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  74. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  75. package/Contexts/ScreenContext/index.tsx +94 -25
  76. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  77. package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
  78. package/events/index.ts +1 -0
  79. package/package.json +5 -5
  80. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  81. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  82. /package/Contexts/{index.js → index.ts} +0 -0
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+ import {
3
+ useNavigationPluginData,
4
+ useIsNavBarVisible,
5
+ useRoute,
6
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
7
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
8
+ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
9
+
10
+ type Return =
11
+ | {
12
+ onContent: true;
13
+ onMenu: false;
14
+ }
15
+ | {
16
+ onContent: false;
17
+ onMenu: true;
18
+ };
19
+
20
+ const getInitialFocus = (focusOnContent, isNavBarVisible): Return => {
21
+ if (focusOnContent) {
22
+ return {
23
+ onContent: true,
24
+ onMenu: false,
25
+ };
26
+ }
27
+
28
+ if (!focusOnContent && isNavBarVisible) {
29
+ // put focus on navbar
30
+ return {
31
+ onContent: false,
32
+ onMenu: true,
33
+ };
34
+ }
35
+
36
+ // we don't have navbar, put focus on content anyway
37
+ return {
38
+ onContent: true,
39
+ onMenu: false,
40
+ };
41
+ };
42
+
43
+ export const useInitialFocus = (): void => {
44
+ const navigationPluginData = useNavigationPluginData();
45
+
46
+ const focusOnContent = toBooleanWithDefaultFalse(
47
+ navigationPluginData?.rules?.focus_on_content
48
+ );
49
+
50
+ const isNavBarVisible = useIsNavBarVisible();
51
+
52
+ const { pathname: currentRoute } = useRoute();
53
+
54
+ React.useEffect(() => {
55
+ const initialFocus = getInitialFocus(focusOnContent, isNavBarVisible);
56
+
57
+ if (initialFocus.onContent) {
58
+ focusManager.setFocusOnContent(currentRoute);
59
+
60
+ return;
61
+ }
62
+
63
+ if (initialFocus.onMenu) {
64
+ focusManager.setFocusOnMenu(currentRoute);
65
+ }
66
+ }, []);
67
+ };
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ import { isNil } from "ramda";
3
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
+ import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
5
+ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
6
+
7
+ export const useRestoreFocus = (): void => {
8
+ const isScreenActive = useIsScreenActive();
9
+ const previousIsScreenActive = usePrevious(isScreenActive);
10
+
11
+ React.useEffect(() => {
12
+ if (isNil(previousIsScreenActive)) {
13
+ // it's initial mounting of the screen, do nothing here
14
+ return;
15
+ }
16
+
17
+ if (!previousIsScreenActive && isScreenActive) {
18
+ // restore focus when we go back from next screen
19
+ focusManager.setInitialFocus();
20
+ }
21
+ }, [previousIsScreenActive, isScreenActive]);
22
+ };
@@ -0,0 +1,174 @@
1
+ import * as React from "react";
2
+ import { last, pathOr } from "ramda";
3
+ import { View, StyleSheet } from "react-native";
4
+ import {
5
+ getNavigationProps,
6
+ getPathAttributes,
7
+ resolveNavigationPlugin,
8
+ } from "@applicaster/zapp-react-native-utils/navigationUtils";
9
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
10
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
11
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
12
+ import { useScreenBackgroundColor } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
13
+ import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
14
+
15
+ import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
16
+ import { ScreenResolver } from "../../ScreenResolver";
17
+ import { useInitialFocus, useRestoreFocus } from "./hooks";
18
+
19
+ const styles = StyleSheet.create({
20
+ container: {
21
+ position: "absolute",
22
+ top: 0,
23
+ left: 0,
24
+ right: 0,
25
+ bottom: 0,
26
+ },
27
+ });
28
+
29
+ type Components = {
30
+ NavBar: React.ComponentType<any>;
31
+ Background: React.ComponentType<any>;
32
+ };
33
+
34
+ type Props = {
35
+ route: string;
36
+ Components: Components;
37
+ };
38
+
39
+ const isPlayer = (routeState): boolean => {
40
+ const pluginType = pathOr(
41
+ "unknown_plugin_type",
42
+ ["state", "screen", "plugin_type"],
43
+ routeState
44
+ );
45
+
46
+ return pluginType === "player";
47
+ };
48
+
49
+ const getActiveRiver = ({
50
+ screenId,
51
+ screenType,
52
+ routeState,
53
+ rivers,
54
+ fallbackActiveRiver,
55
+ }) => {
56
+ if (rivers[screenId]) {
57
+ if (screenType === "hooks") {
58
+ const navigations = routeState?.state?.entry?.payload?.navigations;
59
+
60
+ if (navigations) {
61
+ return routeState.state.entry.payload;
62
+ }
63
+ }
64
+
65
+ return routeState?.state?.screen;
66
+ }
67
+
68
+ // screenId is not presented into rivers, use fallback instead
69
+ return fallbackActiveRiver;
70
+ };
71
+
72
+ const getNavigations = ({
73
+ screenId,
74
+ screenType,
75
+ routeState,
76
+ rivers,
77
+ fallbackNavigations,
78
+ }) => {
79
+ if (rivers[screenId]) {
80
+ // river presents
81
+ if (screenType === "hooks") {
82
+ const navigations = routeState?.state?.entry?.payload?.navigations;
83
+
84
+ if (navigations) {
85
+ return navigations;
86
+ }
87
+ }
88
+
89
+ return routeState?.state?.screen?.navigations;
90
+ }
91
+
92
+ // screenId is not presented into rivers, use fallback instead
93
+ return fallbackNavigations;
94
+ };
95
+
96
+ export const Screen = ({ route, Components }: Props) => {
97
+ if (isNilOrEmpty(route)) {
98
+ throw Error("Required props: route is missing");
99
+ }
100
+
101
+ const navigator = useNavigation();
102
+ const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
103
+
104
+ const pathAttributes = getPathAttributes({ pathname: route });
105
+ const routeState = navigator.getStackForPathname(route);
106
+
107
+ const { screenType, screenId } = last(pathAttributes);
108
+
109
+ const backgroundColor = useScreenBackgroundColor(screenId);
110
+
111
+ useInitialFocus();
112
+ useRestoreFocus();
113
+
114
+ const activeRiver = getActiveRiver({
115
+ screenId,
116
+ screenType,
117
+ routeState,
118
+ rivers,
119
+ fallbackActiveRiver: navigator.activeRiver,
120
+ });
121
+
122
+ const navigationProps = getNavigationProps({
123
+ navigator: {
124
+ // @ts-ignore
125
+ activeRiver,
126
+ // @ts-ignore
127
+ screenTitle: routeState.state.entry?.title || routeState.screen?.name,
128
+ },
129
+ category: "menu",
130
+ });
131
+
132
+ const navigations = getNavigations({
133
+ screenId,
134
+ screenType,
135
+ routeState,
136
+ rivers,
137
+ fallbackNavigations: navigator.activeRiver.navigations,
138
+ });
139
+
140
+ const menuPlugin = resolveNavigationPlugin({
141
+ category: "menu",
142
+ navigations,
143
+ plugins,
144
+ }) as QuickBrickPlugin;
145
+
146
+ const NavBar = (Components.NavBar ||
147
+ menuPlugin.module) as React.ComponentType<any>;
148
+
149
+ const isNavBarVisible = !isPlayer(routeState);
150
+
151
+ const screenData =
152
+ screenType === "hooks"
153
+ ? routeState?.state?.entry
154
+ : routeState?.state?.screen;
155
+
156
+ return (
157
+ <View style={[styles.container, { backgroundColor }]}>
158
+ <NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
159
+ <NavBar
160
+ groupId={route}
161
+ isVisible={isNavBarVisible}
162
+ menuPlugin={menuPlugin}
163
+ navigationProps={navigationProps}
164
+ />
165
+ </NavBarContainer>
166
+ <ScreenResolver
167
+ screenType={screenType}
168
+ screenId={screenId}
169
+ screenData={screenData}
170
+ groupId={route}
171
+ />
172
+ </View>
173
+ );
174
+ };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { create, act } from "react-test-renderer";
3
+ import { act, create } from "react-test-renderer";
4
4
 
5
5
  const Mocked_RouteManager = jest.fn((props) => (
6
6
  <View testID="routeManager" {...props} />
@@ -69,12 +69,16 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
69
69
  isNavBarVisible: mockIsNavBarVisible,
70
70
  useRoute: jest.fn(() => ({
71
71
  pathname: "/river/testId",
72
+ screenData: { id: "testId" },
72
73
  })),
73
74
  useNavigation: jest.fn(() => ({
74
75
  canGoBack: () => false,
75
76
  currentRoute: "/river/testId",
77
+ activeRiver: { id: "testId" },
78
+ screenData: { id: "testId" },
76
79
  data: { screen: { id: "testId" } },
77
80
  })),
81
+ useIsScreenActive: jest.fn().mockReturnValue(true),
78
82
  }));
79
83
 
80
84
  jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
@@ -11,7 +11,9 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
11
11
  }
12
12
  >
13
13
  <View
14
+ hasMenu={false}
14
15
  id="/river/testId"
16
+ pathname="/river/testId"
15
17
  selected="testId"
16
18
  testID="navBar"
17
19
  title=""
@@ -19,6 +21,11 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
19
21
  <View>
20
22
  <View
21
23
  pathname="/river/testId"
24
+ screenData={
25
+ Object {
26
+ "id": "testId",
27
+ }
28
+ }
22
29
  testID="routeManager"
23
30
  />
24
31
  </View>
@@ -36,7 +43,9 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
36
43
  }
37
44
  >
38
45
  <View
46
+ hasMenu={false}
39
47
  id="/river/testId"
48
+ pathname="/river/testId"
40
49
  selected="testId"
41
50
  testID="navBar"
42
51
  title=""
@@ -44,6 +53,11 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
44
53
  <View>
45
54
  <View
46
55
  pathname="/river/testId"
56
+ screenData={
57
+ Object {
58
+ "id": "testId",
59
+ }
60
+ }
47
61
  testID="routeManager"
48
62
  />
49
63
  </View>
@@ -6,7 +6,10 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
6
 
7
7
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
8
8
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
9
- import { getNavigationPropsV2 } from "@applicaster/zapp-react-native-utils/navigationUtils";
9
+ import {
10
+ getNavigationPropsV2,
11
+ resolveNavigationPlugin,
12
+ } from "@applicaster/zapp-react-native-utils/navigationUtils";
10
13
  import { useSafeAreaInsets } from "react-native-safe-area-context";
11
14
  import {
12
15
  useDimensions,
@@ -14,6 +17,7 @@ import {
14
17
  useCurrentScreenData,
15
18
  useNavbarState,
16
19
  useScreenData,
20
+ useNavigation,
17
21
  } from "@applicaster/zapp-react-native-utils/reactHooks";
18
22
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
19
23
 
@@ -22,6 +26,17 @@ import { RouteManager } from "../RouteManager";
22
26
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
23
27
  import { useScreenOrientationHandler } from "./orientationHandler";
24
28
 
29
+ const getScreenId = (
30
+ screenData: LegacyNavigationScreenData,
31
+ fallbackRiver: ZappRiver
32
+ ) => {
33
+ return screenData?.targetScreen
34
+ ? screenData?.targetScreen?.id ?? fallbackRiver.id
35
+ : "screen_id" in screenData
36
+ ? screenData.screen_id
37
+ : fallbackRiver.id;
38
+ };
39
+
25
40
  function colorIsNotTransparent(color) {
26
41
  const layers = R.compose(
27
42
  R.map(R.trim),
@@ -40,14 +55,13 @@ function isValidColor(string) {
40
55
  }
41
56
 
42
57
  type Props = {
43
- pathname: string;
58
+ pathname: unknown;
44
59
  screenData: unknown;
45
- setToggleMenu: () => void;
46
- setCloseMenu: () => void;
47
60
  };
48
61
 
49
- export function Screen({ setToggleMenu, setCloseMenu }: Props) {
62
+ export function Screen(_props: Props) {
50
63
  const theme = useTheme<BaseThemePropertiesMobile>();
64
+ const navigation = useNavigation();
51
65
  const { plugins } = usePickFromState(["plugins"]);
52
66
 
53
67
  // Gets the data for the current screen configuration
@@ -59,28 +73,38 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
59
73
  fullDimensions: true,
60
74
  });
61
75
 
62
- const routeData = useRoute();
76
+ const { screenData, pathname } = useRoute();
63
77
 
64
78
  const currentRiver = useScreenData(
65
- (routeData.screenData as ZappRiver)?.targetScreen
66
- ? (routeData.screenData as ZappRiver)?.targetScreen.id
67
- : (routeData.screenData as ZappRiver)?.screen_id
79
+ getScreenId(screenData, navigation.activeRiver)
68
80
  );
69
81
 
70
82
  const { title } = useNavbarState();
71
83
 
72
- const navBarProps = React.useMemo(
73
- () => ({
74
- ...getNavigationPropsV2({
75
- currentRiver,
76
- title,
77
- category: "nav_bar",
78
- }),
79
- setToggleMenu,
80
- setCloseMenu,
81
- }),
82
- [currentRiver, setCloseMenu, setToggleMenu]
83
- );
84
+ const hasMenu =
85
+ resolveNavigationPlugin({
86
+ category: "menu",
87
+ navigations: currentRiver.navigations,
88
+ plugins,
89
+ })?.identifier === "quick_brick_side_menu";
90
+
91
+ const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
92
+ const props = getNavigationPropsV2({
93
+ currentRiver,
94
+ title,
95
+ category: "nav_bar",
96
+ });
97
+
98
+ if (props) {
99
+ return {
100
+ ...props,
101
+ id: pathname,
102
+ pathname: pathname,
103
+ };
104
+ }
105
+
106
+ return null;
107
+ }, [currentRiver, pathname]);
84
108
 
85
109
  const NavBar = React.useMemo(
86
110
  () =>
@@ -88,12 +112,10 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
88
112
  "nav_bar",
89
113
  currentRiver,
90
114
  plugins
91
- ) as React.ComponentType<MobileNavBarPluginProps>,
115
+ ) as React.ComponentType<MobileNavBarPluginProps & { hasMenu: boolean }>,
92
116
  []
93
117
  );
94
118
 
95
- const { screenData, pathname } = routeData;
96
-
97
119
  const offlinePlugin = getComponentModule({
98
120
  plugins,
99
121
  components: {},
@@ -124,11 +146,9 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
124
146
  return (
125
147
  <ScreenContextProvider pathname={pathname}>
126
148
  <View style={style}>
127
- <NavBar
128
- {...{ ...(navBarProps as MobileNavBarPluginProps), id: pathname }}
129
- />
149
+ {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
130
150
 
131
- <OfflineFallbackScreen screenData={screenData}>
151
+ <OfflineFallbackScreen screenData={targetScreenData}>
132
152
  {/* @TODO RouteManager doesn't use props, can they be removed ? */}
133
153
  <RouteManager pathname={pathname} screenData={screenData} />
134
154
  </OfflineFallbackScreen>
@@ -32,12 +32,13 @@ type Props = {
32
32
  nextFocusLeft?: React.Ref<any>;
33
33
  nextFocusUp?: React.Ref<any>;
34
34
  };
35
+ groupId?: string;
35
36
  };
36
37
 
37
38
  export function ScreenResolverComponent(props: Props) {
38
39
  useScreenAnalytics(props);
39
40
 
40
- const { screenType, screenId, screenData } = props;
41
+ const { screenType, screenId, screenData, groupId } = props;
41
42
 
42
43
  const { hookPlugin } = screenData || {};
43
44
 
@@ -81,6 +82,7 @@ export function ScreenResolverComponent(props: Props) {
81
82
  item={screenData}
82
83
  mode={mode === "PIP" ? "PIP" : "FULLSCREEN"}
83
84
  isModal={false}
85
+ groupId={groupId}
84
86
  />
85
87
  );
86
88
  }
@@ -78,7 +78,7 @@ export const getStyles = (config): Partial<TVTabsStyles> => {
78
78
  },
79
79
  tvos: {
80
80
  marginTop: -1,
81
- }
81
+ },
82
82
  }),
83
83
  },
84
84
  tabsBackground: {
@@ -14,7 +14,7 @@ import {
14
14
  } from "@applicaster/zapp-react-native-utils/reactUtils";
15
15
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
16
16
  import { getUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
17
- import { PlayerImageBackground } from "../PlayerImageBackground";
17
+ import Image from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/Image";
18
18
  import { LiveImage, LiveImageManager, LiveImageType } from "./LiveImageManager";
19
19
 
20
20
  import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
@@ -39,12 +39,13 @@ type Props = {
39
39
  imageKey?: string;
40
40
  screenConfig: Record<string, any>;
41
41
  audioMutedByDefault?: boolean;
42
+ uri: string; // cover image url
42
43
  };
43
44
 
44
45
  const PlayerLiveImageComponent = (props: Props) => {
45
46
  const dimensions = useDimensions("screen", { fullDimensions: true });
46
47
 
47
- const { item, style, playerId, imageKey } = props;
48
+ const { item, style, playerId } = props;
48
49
 
49
50
  const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
50
51
  const [mode, setMode] = React.useState(LiveImageType.Image);
@@ -63,24 +64,27 @@ const PlayerLiveImageComponent = (props: Props) => {
63
64
  *
64
65
  * @param type video or image
65
66
  */
66
- const setModeDebounced = React.useCallback((type: LiveImageType) => {
67
- if (type === LiveImageType.Video) {
68
- if (type === mode) {
69
- return;
70
- }
67
+ const setModeDebounced = React.useCallback(
68
+ (type: LiveImageType) => {
69
+ if (type === LiveImageType.Video) {
70
+ if (type === mode) {
71
+ return;
72
+ }
73
+
74
+ timeoutRef.current = setTimeout(() => {
75
+ setMode(type);
76
+ }, 1000) as unknown as NodeJS.Timeout;
77
+ } else {
78
+ if (timeoutRef.current) {
79
+ clearTimeout(timeoutRef.current);
80
+ timeoutRef.current = null;
81
+ }
71
82
 
72
- timeoutRef.current = setTimeout(() => {
73
83
  setMode(type);
74
- }, 1000) as unknown as NodeJS.Timeout;
75
- } else {
76
- if (timeoutRef.current) {
77
- clearTimeout(timeoutRef.current);
78
- timeoutRef.current = null;
79
84
  }
80
-
81
- setMode(type);
82
- }
83
- }, [mode]);
85
+ },
86
+ [mode]
87
+ );
84
88
 
85
89
  const { screenConfig, playerPluginId } = props;
86
90
 
@@ -100,7 +104,7 @@ const PlayerLiveImageComponent = (props: Props) => {
100
104
  return new LiveImage({
101
105
  playerId,
102
106
  player: playerFactoryItem.controller,
103
- component: playerFactoryItem?.Component
107
+ component: playerFactoryItem?.Component,
104
108
  });
105
109
  } else {
106
110
  throw new Error("Player factory item is null");
@@ -111,10 +115,7 @@ const PlayerLiveImageComponent = (props: Props) => {
111
115
  liveImageItem.setMode = setModeDebounced;
112
116
  }, [setModeDebounced, liveImageItem]);
113
117
 
114
- const { start, end } = React.useMemo(
115
- () => getAutoplaySettings(item),
116
- [item]
117
- );
118
+ const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
118
119
 
119
120
  const controller = liveImageItem.getPlayer();
120
121
  const player = usePlayer(playerId);
@@ -239,7 +240,12 @@ const PlayerLiveImageComponent = (props: Props) => {
239
240
 
240
241
  const onPositionUpdated = React.useCallback(
241
242
  (data) => {
242
- const normalizedRect = (rect: {left: number, right: number, top: number, bottom: number }) => {
243
+ const normalizedRect = (rect: {
244
+ left: number;
245
+ right: number;
246
+ top: number;
247
+ bottom: number;
248
+ }) => {
243
249
  if (!rect) {
244
250
  return null;
245
251
  }
@@ -283,6 +289,7 @@ const PlayerLiveImageComponent = (props: Props) => {
283
289
  const videoStyles = { ...style, position: "absolute", zIndex: -100 };
284
290
  const Player: any = liveImageItem.component || BufferAnimation;
285
291
 
292
+ // TODO: nice to have - resolve imageKey when imageUrl is not provided
286
293
  return (
287
294
  <TrackedView
288
295
  testId={`tracked-view-${playerId}-${item.title}`}
@@ -307,11 +314,7 @@ const PlayerLiveImageComponent = (props: Props) => {
307
314
  animationConfig={overlayFadeIn}
308
315
  staticStyles={style}
309
316
  >
310
- <PlayerImageBackground
311
- entry={item}
312
- style={style}
313
- imageKey={imageKey}
314
- />
317
+ <Image {...props} resizeMode="cover" style={style} applyMaxSize />
315
318
  </AnimatedInOut>
316
319
  }
317
320
  </TrackedView>