@applicaster/zapp-react-native-utils 14.0.38-alpha.2343523156 → 14.0.39

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.
@@ -73,17 +73,14 @@ type Props = {
73
73
  children: React.ReactNode;
74
74
  };
75
75
 
76
- function findParentComponent(
77
- childId: string,
78
- parent: ZappRiver | ZappUIComponent
79
- ): ZappRiver | ZappUIComponent | null {
80
- for (const child of parent.ui_components) {
81
- if (child.id === childId) return parent;
82
-
83
- if (child.ui_components) {
84
- const found = findParentComponent(childId, child);
85
- if (found) return found;
86
- }
76
+ /** Prefer component data.source, otherwise direct UIComponentContext parent. */
77
+ function getComponentFeedData(component) {
78
+ if (component?.data?.source) {
79
+ return component.data;
80
+ }
81
+
82
+ if (component?.parent?.data?.source) {
83
+ return component.parent.data;
87
84
  }
88
85
 
89
86
  return null;
@@ -111,16 +108,7 @@ const prepareDefaultActions = (actionExecutor) => {
111
108
  async (_action, context) => {
112
109
  const dispatch = appStore.getDispatch();
113
110
 
114
- const parentComponent = findParentComponent(
115
- context?.component?.id,
116
- context?.screenData
117
- );
118
-
119
- const componentSource = context?.component?.data?.source;
120
-
121
- const componentData = componentSource
122
- ? context.component.data
123
- : parentComponent?.data;
111
+ const componentData = getComponentFeedData(context?.component);
124
112
 
125
113
  const source = componentData?.source;
126
114
  const mapping = componentData?.mapping;
@@ -723,21 +723,6 @@ function getPlayerConfiguration({ platform, version }) {
723
723
  }
724
724
  );
725
725
 
726
- if (
727
- platform.includes("android") ||
728
- platform.includes("amazon") ||
729
- platform.includes("ios") ||
730
- platform.includes("tvos")
731
- ) {
732
- general.fields.push({
733
- key: "user_agent",
734
- label: "User agent",
735
- initial_value: "",
736
- type: "text_input",
737
- label_tooltip: "Override default user agent string",
738
- });
739
- }
740
-
741
726
  if (platform === "android_for_quickbrick") {
742
727
  general.fields.push({
743
728
  key: "stop_playback_on_task_removal",
@@ -2357,6 +2342,21 @@ function getPlayerConfiguration({ platform, version }) {
2357
2342
  );
2358
2343
  }
2359
2344
 
2345
+ if (
2346
+ platform.includes("android") ||
2347
+ platform.includes("amazon") ||
2348
+ platform.includes("ios") ||
2349
+ platform.includes("tvos")
2350
+ ) {
2351
+ general.fields.push({
2352
+ key: "user_agent",
2353
+ label: "User agent",
2354
+ initial_value: "",
2355
+ type: "text_input",
2356
+ label_tooltip: "Override default user agent string",
2357
+ });
2358
+ }
2359
+
2360
2360
  compact([
2361
2361
  {
2362
2362
  key: "liveCatchUpEnabled",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "14.0.38-alpha.2343523156",
3
+ "version": "14.0.39",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
29
29
  "dependencies": {
30
- "@applicaster/applicaster-types": "14.0.38-alpha.2343523156",
30
+ "@applicaster/applicaster-types": "14.0.39",
31
31
  "buffer": "^5.2.1",
32
32
  "camelize": "^1.0.0",
33
33
  "dayjs": "^1.11.10",
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import * as R from "ramda";
5
5
  import { handleActionSchemeUrl } from "@applicaster/quick-brick-core/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/useUrlSchemeHandler";
6
6
  import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
7
+ import { useUIComponentContext } from "@applicaster/zapp-react-native-ui-components/Contexts/UIComponentContext";
7
8
  import {
8
9
  useNavigation,
9
10
  useProfilerLogging,
@@ -28,7 +29,6 @@ import { useScreenStateStore } from "../navigation/useScreenStateStore";
28
29
  type Props = {
29
30
  item?: ZappEntry;
30
31
  index?: number;
31
- component?: ZappUIComponent;
32
32
  zappPipesData?: ZappPipesData;
33
33
  };
34
34
 
@@ -37,16 +37,16 @@ type onPressReturnFn =
37
37
  | (() => void);
38
38
 
39
39
  export const useCellClick = ({
40
- component,
41
40
  zappPipesData,
42
41
  item,
43
- }: Props): onPressReturnFn => {
42
+ }: Props = {}): onPressReturnFn => {
44
43
  const { push, currentRoute } = useNavigation();
45
44
  const { pathname } = useRoute();
46
45
  const screenStateStore = useScreenStateStore();
47
46
 
48
47
  const onCellTap: Option<Function> = React.useContext(CellTapContext);
49
48
  const actionExecutor = React.useContext(ActionExecutorContext);
49
+ const component = useUIComponentContext();
50
50
  const screenData = useCurrentScreenData();
51
51
  const screenState = useScreenContext()?.options;
52
52
 
@@ -38,3 +38,7 @@ export const useNavigationPluginData = jest.fn().mockReturnValue(mockMenu);
38
38
  export const useIsNavBarVisible = jest.fn().mockReturnValue(true);
39
39
 
40
40
  export const useIsScreenActive = jest.fn().mockReturnValue(true);
41
+
42
+ export const isScreenActiveForRoute = jest.fn(
43
+ (route, currentRoute) => route === currentRoute
44
+ );
@@ -0,0 +1,42 @@
1
+ import { isScreenActiveForRoute } from "../useIsScreenActive";
2
+
3
+ describe("isScreenActiveForRoute", () => {
4
+ const route = "/river/home/river/tabs";
5
+ const currentRoute = "/river/home/river/tabs";
6
+
7
+ it("returns false when route does not match", () => {
8
+ expect(
9
+ isScreenActiveForRoute(route, "/river/home", { visible: false })
10
+ ).toBe(false);
11
+ });
12
+
13
+ it("keeps underlying screen active when video modal is docked", () => {
14
+ expect(
15
+ isScreenActiveForRoute(route, currentRoute, {
16
+ visible: true,
17
+ mode: "MINIMIZED",
18
+ })
19
+ ).toBe(true);
20
+ });
21
+
22
+ it.each(["FULLSCREEN", "MAXIMIZED", "PIP"])(
23
+ "deactivates underlying screen when video modal is visible",
24
+ (mode) => {
25
+ expect(
26
+ isScreenActiveForRoute(route, currentRoute, {
27
+ visible: true,
28
+ mode,
29
+ })
30
+ ).toBe(false);
31
+ }
32
+ );
33
+
34
+ it("keeps video-modal route active when video modal is open", () => {
35
+ expect(
36
+ isScreenActiveForRoute("video-modal/123", currentRoute, {
37
+ visible: true,
38
+ mode: "FULLSCREEN",
39
+ })
40
+ ).toBe(true);
41
+ });
42
+ });
@@ -30,7 +30,7 @@ export { useNavigationType } from "./useNavigationType";
30
30
 
31
31
  export { useGetBottomTabBarHeight } from "./useGetBottomTabBarHeight";
32
32
 
33
- export { useIsScreenActive } from "./useIsScreenActive";
33
+ export { useIsScreenActive, isScreenActiveForRoute } from "./useIsScreenActive";
34
34
 
35
35
  export { useProfilerLogging } from "./useProfilerLogging";
36
36
 
@@ -2,20 +2,41 @@ import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtil
2
2
  import { useNavigation } from "./useNavigation";
3
3
  import { usePathname } from "./usePathname";
4
4
 
5
- // If current screen is active/focused (visible to the user)
6
- export const useIsScreenActive = () => {
7
- const pathname = usePathname();
8
- const { currentRoute, videoModalState } = useNavigation();
5
+ type VideoModalState = {
6
+ visible?: boolean;
7
+ mode?: string;
8
+ } | null;
9
9
 
10
- if (videoModalState.visible) {
11
- if (pathname.includes(ROUTE_TYPES.VIDEO_MODAL)) {
10
+ /**
11
+ * Whether a navigation route should be treated as the active/focused screen.
12
+ * Docked (MINIMIZED) video modal does not deactivate the underlying screen —
13
+ * only FULLSCREEN / MAXIMIZED / PIP do.
14
+ */
15
+ export function isScreenActiveForRoute(
16
+ route: string,
17
+ currentRoute: string,
18
+ videoModalState: VideoModalState
19
+ ) {
20
+ if (videoModalState?.visible) {
21
+ if (route.includes(ROUTE_TYPES.VIDEO_MODAL)) {
12
22
  return true;
13
23
  }
14
24
 
15
- if (["FULLSCREEN", "MAXIMIZED", "PIP"].includes(videoModalState.mode)) {
25
+ if (
26
+ ["FULLSCREEN", "MAXIMIZED", "PIP"].includes(videoModalState.mode ?? "")
27
+ ) {
16
28
  return false;
17
29
  }
30
+ // MINIMIZED (docked): fall through — underlying screen stays active
18
31
  }
19
32
 
20
- return pathname === currentRoute;
33
+ return route === currentRoute;
34
+ }
35
+
36
+ // If current screen is active/focused (visible to the user)
37
+ export const useIsScreenActive = () => {
38
+ const pathname = usePathname();
39
+ const { currentRoute, videoModalState } = useNavigation();
40
+
41
+ return isScreenActiveForRoute(pathname, currentRoute, videoModalState);
21
42
  };