@applicaster/zapp-react-native-utils 15.0.0-rc.99 → 15.1.0-rc.1

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 (137) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +51 -5
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/README.md +1 -1
  5. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +188 -0
  6. package/appUtils/HooksManager/__tests__/hooksManager.test.js +2 -16
  7. package/appUtils/HooksManager/index.ts +45 -10
  8. package/appUtils/RiverFocusManager/{index.ts → index.js} +18 -25
  9. package/appUtils/accessibilityManager/const.ts +0 -4
  10. package/appUtils/accessibilityManager/utils.ts +1 -0
  11. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +2 -7
  12. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +0 -48
  13. package/appUtils/contextKeysManager/contextResolver.ts +22 -51
  14. package/appUtils/contextKeysManager/index.ts +10 -65
  15. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +0 -3
  16. package/appUtils/focusManager/index.ios.ts +4 -43
  17. package/appUtils/focusManagerAux/utils/index.ts +3 -5
  18. package/appUtils/focusManagerAux/utils/utils.ios.ts +3 -199
  19. package/appUtils/keyCodes/keys/keys.web.ts +4 -1
  20. package/appUtils/localizationsHelper.ts +4 -0
  21. package/appUtils/orientationHelper.ts +4 -2
  22. package/appUtils/platform/platformUtils.ts +1 -1
  23. package/appUtils/playerManager/index.ts +9 -0
  24. package/appUtils/playerManager/player.ts +1 -5
  25. package/appUtils/playerManager/playerNative.ts +22 -30
  26. package/appUtils/playerManager/usePlayer.tsx +5 -3
  27. package/appUtils/playerManager/usePlayerState.tsx +2 -14
  28. package/cellUtils/__tests__/cellUtils.test.ts +39 -0
  29. package/cellUtils/index.ts +11 -1
  30. package/cloudEventsUtils/index.ts +1 -65
  31. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  32. package/dateUtils/__tests__/dayjs.test.ts +0 -3
  33. package/dateUtils/index.ts +2 -0
  34. package/focusManager/aux/index.ts +1 -1
  35. package/headersUtils/__tests__/headersUtils.test.js +1 -11
  36. package/headersUtils/index.ts +1 -2
  37. package/manifestUtils/defaultManifestConfigurations/player.js +7 -75
  38. package/manifestUtils/tvAction/container/index.js +1 -1
  39. package/numberUtils/__tests__/toNumber.test.ts +0 -12
  40. package/numberUtils/index.ts +1 -19
  41. package/package.json +4 -4
  42. package/pluginUtils/index.ts +4 -9
  43. package/reactHooks/advertising/index.ts +2 -2
  44. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  45. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  46. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +2 -1
  47. package/reactHooks/casting/index.ts +1 -0
  48. package/reactHooks/casting/useIsCasting.tsx +57 -0
  49. package/reactHooks/cell-click/__tests__/index.test.js +3 -1
  50. package/reactHooks/componentsMap/index.ts +55 -0
  51. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  52. package/reactHooks/connection/__tests__/index.test.js +1 -1
  53. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  54. package/reactHooks/device/useIsTablet.tsx +19 -14
  55. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  56. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +23 -32
  57. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  58. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -4
  59. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +30 -42
  60. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
  61. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  62. package/reactHooks/feed/useBatchLoading.ts +1 -7
  63. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  64. package/reactHooks/feed/useInflatedUrl.ts +1 -1
  65. package/reactHooks/feed/usePipesCacheReset.ts +1 -3
  66. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -13
  67. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  68. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  69. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.tsx → useDimensions.test.ts} +25 -105
  70. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  71. package/reactHooks/navigation/__tests__/index.test.tsx +4 -2
  72. package/reactHooks/navigation/index.ts +6 -7
  73. package/reactHooks/navigation/useRoute.ts +6 -8
  74. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +10 -27
  75. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  76. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  77. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  78. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  79. package/reactHooks/resolvers/useCellResolver.ts +2 -6
  80. package/reactHooks/resolvers/useComponentResolver.ts +13 -9
  81. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  82. package/reactHooks/screen/__tests__/useCurrentScreenIsHook.test.ts +103 -0
  83. package/reactHooks/screen/__tests__/useCurrentScreenIsStartupHook.test.ts +94 -0
  84. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  85. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  86. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +4 -12
  87. package/reactHooks/screen/index.ts +6 -0
  88. package/reactHooks/screen/useCurrentScreenIsHook.ts +9 -0
  89. package/reactHooks/screen/useCurrentScreenIsStartupHook.ts +8 -0
  90. package/reactHooks/screen/useIsStandaloneFullscreen.ts +12 -0
  91. package/reactHooks/screen/useTargetScreenData.ts +2 -4
  92. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  93. package/reactHooks/state/index.ts +2 -0
  94. package/reactHooks/state/useComponentScreenState.ts +45 -0
  95. package/reactHooks/state/useRivers.ts +1 -1
  96. package/reactHooks/usePluginConfiguration.ts +2 -2
  97. package/reactHooks/utils/__tests__/index.test.js +1 -1
  98. package/rectUtils/index.ts +2 -2
  99. package/screenPickerUtils/index.ts +5 -0
  100. package/screenState/__tests__/index.test.ts +1 -1
  101. package/stringUtils/index.ts +1 -1
  102. package/testUtils/index.tsx +21 -30
  103. package/typeGuards/index.ts +0 -4
  104. package/utils/__tests__/clone.test.ts +158 -0
  105. package/utils/clone.ts +7 -0
  106. package/utils/index.ts +1 -13
  107. package/utils/path.ts +3 -6
  108. package/utils/pathOr.ts +1 -5
  109. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +1 -1
  110. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  111. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  112. package/adsUtils/__tests__/createVMAP.test.ts +0 -419
  113. package/appDataUtils/__tests__/urlScheme.test.ts +0 -678
  114. package/appUtils/focusManagerAux/utils/index.ios.ts +0 -122
  115. package/cloudEventsUtils/__tests__/index.test.ts +0 -529
  116. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +0 -207
  117. package/errorUtils/__tests__/GeneralError.test.ts +0 -97
  118. package/errorUtils/__tests__/HttpStatusCode.test.ts +0 -344
  119. package/errorUtils/__tests__/MissingPluginError.test.ts +0 -113
  120. package/errorUtils/__tests__/NetworkError.test.ts +0 -202
  121. package/errorUtils/__tests__/getParsedResponse.test.ts +0 -188
  122. package/errorUtils/__tests__/invariant.test.ts +0 -112
  123. package/numberUtils/__tests__/toPositiveNumber.test.ts +0 -165
  124. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +0 -537
  125. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +0 -188
  126. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +0 -580
  127. package/rectUtils/__tests__/index.test.ts +0 -549
  128. package/screenPickerUtils/__tests__/index.test.ts +0 -333
  129. package/searchUtils/const.ts +0 -7
  130. package/searchUtils/index.ts +0 -3
  131. package/time/__tests__/BackgroundTimer.test.ts +0 -156
  132. package/time/__tests__/Timer.test.ts +0 -236
  133. package/typeGuards/__tests__/isString.test.ts +0 -21
  134. package/utils/__tests__/mergeRight.test.ts +0 -48
  135. package/utils/__tests__/selectors.test.ts +0 -124
  136. package/utils/mergeRight.ts +0 -5
  137. package/utils/selectors.ts +0 -46
@@ -49,7 +49,7 @@ export const findSelectedMenuId = (
49
49
  ) => {
50
50
  const sectionName = QUICK_BRICK_NAVBAR_SECTIONS[sectionKey];
51
51
 
52
- return pathOr<string | undefined>(
52
+ return pathOr(
53
53
  undefined,
54
54
  ["children", index, "id"],
55
55
  focusableTree.find(sectionName)
@@ -1,15 +1,6 @@
1
1
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
2
2
  import { getAppDataHeaders } from "../index";
3
3
 
4
- const mockUILanguage = "en-US";
5
-
6
- jest.mock(
7
- "@applicaster/zapp-react-native-utils/appUtils/localizationsHelper",
8
- () => ({
9
- getUILanguage: jest.fn(() => mockUILanguage),
10
- })
11
- );
12
-
13
4
  describe("getAppDataHeaders", () => {
14
5
  const mockAppData = {
15
6
  riversConfigurationId: "test-layout",
@@ -34,7 +25,7 @@ describe("getAppDataHeaders", () => {
34
25
  const expectedHeaders = {
35
26
  "x-applicaster-layout-id": mockAppData.riversConfigurationId,
36
27
  "x-applicaster-screen-id": screenId,
37
- "x-applicaster-language-code": mockUILanguage,
28
+ "x-applicaster-language-code": mockAppData.languageCode,
38
29
  "x-applicaster-version-number": mockAppData.version_name,
39
30
  "x-applicaster-platform": mockAppData.platform,
40
31
  "x-applicaster-country-code": mockAppData.countryCode,
@@ -42,7 +33,6 @@ describe("getAppDataHeaders", () => {
42
33
  mockAppData.signedDeviceInfoToken,
43
34
  "x-applicaster-device-make": mockAppData.deviceMake,
44
35
  "x-applicaster-device-model": mockAppData.deviceModel,
45
- "x-applicaster-uuid": undefined,
46
36
  };
47
37
 
48
38
  const headers = getAppDataHeaders(screenId);
@@ -1,7 +1,6 @@
1
1
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
2
2
  import { getPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
3
3
  import { utilsLogger } from "../logger";
4
- import { getUILanguage } from "../localizationUtils";
5
4
 
6
5
  const logger = utilsLogger.addSubsystem("headersUtils");
7
6
 
@@ -22,7 +21,7 @@ export const getAppDataHeaders = (screenId: string) => {
22
21
  "x-applicaster-layout-id":
23
22
  appData.riversConfigurationId || appData.rivers_configuration_id,
24
23
  "x-applicaster-screen-id": screenId,
25
- "x-applicaster-language-code": getUILanguage(),
24
+ "x-applicaster-language-code": appData.languageCode,
26
25
  "x-applicaster-version-number": appData.version_name || appData.versionName,
27
26
  "x-applicaster-platform": (platform || appData.platform).toLowerCase(),
28
27
  "x-applicaster-country-code": appData.countryCode,
@@ -123,6 +123,12 @@ function getPlayerConfiguration({ platform, version }) {
123
123
  key: "skip_button_localization_text_skip_intro",
124
124
  initial_value: "Skip Intro",
125
125
  },
126
+ {
127
+ type: "text_input",
128
+ label: "Stream error message",
129
+ key: "stream_error_message",
130
+ initial_value: "Cannot play stream",
131
+ },
126
132
  {
127
133
  type: "text_input",
128
134
  label: "Locked message",
@@ -364,20 +370,6 @@ function getPlayerConfiguration({ platform, version }) {
364
370
  };
365
371
 
366
372
  if (isTV(platform)) {
367
- localizations.fields.push({
368
- key: "back_to_live_label",
369
- label: "Back to live label",
370
- initial_value: "Back To Live",
371
- type: "text_input",
372
- });
373
-
374
- localizations.fields.push({
375
- key: "start_over_label",
376
- label: "Start over label",
377
- initial_value: "Start Over",
378
- type: "text_input",
379
- });
380
-
381
373
  styles.fields.push(
382
374
  fieldsGroup("Always Show Scrub Bar & Timestamp", "", [
383
375
  {
@@ -490,7 +482,7 @@ function getPlayerConfiguration({ platform, version }) {
490
482
  ),
491
483
  fieldsGroup(
492
484
  "Skip Button",
493
- "This section allows you to configure the skip button behaviour",
485
+ "This section allows you to configure the skip button styles for tv",
494
486
  [
495
487
  {
496
488
  type: "switch",
@@ -507,12 +499,6 @@ function getPlayerConfiguration({ platform, version }) {
507
499
  label: "Persistent Button Toggle",
508
500
  initial_value: true,
509
501
  },
510
- ]
511
- ),
512
- fieldsGroup(
513
- "Labeled Button Style",
514
- "This section allows you to configure the labeled button styles",
515
- [
516
502
  {
517
503
  type: "color_picker_rgba",
518
504
  label_tooltip: "",
@@ -668,61 +654,7 @@ function getPlayerConfiguration({ platform, version }) {
668
654
  );
669
655
  }
670
656
 
671
- if (isTV(platform)) {
672
- general.fields.push(
673
- {
674
- key: "liveSeekingEnabled",
675
- label: "Live Seeking Enabled",
676
- initial_value: false,
677
- type: "switch",
678
- label_tooltip: "Enable Live Seek",
679
- },
680
- {
681
- key: "minimumAllowedSeekableDurationInSeconds",
682
- label: "Minimum allowed seekable duration in seconds",
683
- initial_value: 300,
684
- type: "number_input",
685
- label_tooltip:
686
- "If duration less than this value, player will disable 'liveSeekingEnabled' value",
687
- },
688
- {
689
- key: "live_image",
690
- label: "Live badge",
691
- type: "uploader",
692
- label_tooltip: "Override default live badge / icon",
693
- },
694
- {
695
- key: "live_width",
696
- label: "Live badge width",
697
- type: "number_input",
698
- initial_value: 85,
699
- },
700
- {
701
- key: "live_height",
702
- label: "Live badge height",
703
- type: "number_input",
704
- initial_value: 50,
705
- }
706
- );
707
- }
708
-
709
657
  if (isMobile(platform)) {
710
- localizations.fields.push(
711
- {
712
- type: "text_input",
713
- label: "Restrict playback on mobile networks alert title",
714
- key: "mobile_connection_restricted_alert_title",
715
- initial_value: "Restricted Connection Type",
716
- },
717
- {
718
- type: "text_input",
719
- label: "Restrict playback on mobile networks alert message",
720
- key: "mobile_connection_restricted_alert_message",
721
- initial_value:
722
- "This content can only be viewed over a Wi-Fi or LAN network.",
723
- }
724
- );
725
-
726
658
  general.fields.push(
727
659
  {
728
660
  section: "Default Timestamp Type",
@@ -38,7 +38,7 @@ function tvActionButtonsContainer({ label, description, defaults }) {
38
38
  generateFieldsFromDefaultsWithoutPrefixedLabel(
39
39
  label,
40
40
  defaults,
41
- tvActionButtonContainerFields(defaults.position)
41
+ tvActionButtonContainerFields(defaults["position"])
42
42
  )
43
43
  );
44
44
 
@@ -11,16 +11,6 @@ describe("toNumber", () => {
11
11
  });
12
12
  });
13
13
 
14
- it("return number if input is BigInt", () => {
15
- const inputs = [5n, -5n];
16
- expect.assertions(inputs.length);
17
-
18
- inputs.forEach((input) => {
19
- const output = toNumber(input);
20
- expect(output).toBe(Number(input));
21
- });
22
- });
23
-
24
14
  it("return number if input is string as number", () => {
25
15
  const inputs = ["-1", "0", "1", "100", "0.2"];
26
16
  expect.assertions(inputs.length);
@@ -42,8 +32,6 @@ describe("toNumber", () => {
42
32
  { test: 1 },
43
33
  [],
44
34
  [1],
45
- "5n",
46
- "-5n",
47
35
  ];
48
36
 
49
37
  expect.assertions(inputs.length);
@@ -8,7 +8,7 @@ export const toNumber = (value: unknown): number | undefined => {
8
8
  return undefined;
9
9
  }
10
10
 
11
- if (R.is(Number, value) || R.is(BigInt, value) || R.is(String, value)) {
11
+ if (R.is(Number, value) || R.is(String, value)) {
12
12
  const numberOrNan = Number(value);
13
13
 
14
14
  return Number.isNaN(numberOrNan) ? undefined : numberOrNan;
@@ -69,24 +69,6 @@ export const isMinusZero = (value: number) => {
69
69
  return 1 / value === -Infinity;
70
70
  };
71
71
 
72
- export const toPositiveNumber = (value: unknown): number | undefined => {
73
- const possibleNumber = toNumber(value);
74
-
75
- if (R.isNil(possibleNumber)) {
76
- return undefined;
77
- }
78
-
79
- if (possibleNumber < 0) {
80
- return undefined;
81
- }
82
-
83
- if (isZero(possibleNumber)) {
84
- return undefined;
85
- }
86
-
87
- return possibleNumber;
88
- };
89
-
90
72
  export const toPositiveNumberWithDefault = (
91
73
  defaultValue: number,
92
74
  value: unknown
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "15.0.0-rc.99",
3
+ "version": "15.1.0-rc.1",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,13 +27,13 @@
27
27
  },
28
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
29
29
  "dependencies": {
30
- "@applicaster/applicaster-types": "15.0.0-rc.99",
30
+ "@applicaster/applicaster-types": "15.1.0-rc.1",
31
31
  "buffer": "^5.2.1",
32
32
  "camelize": "^1.0.0",
33
33
  "dayjs": "^1.11.10",
34
- "handlebars": "4.7.8",
35
34
  "memoizee": "0.4.15",
36
- "prop-types": "^15.0.0"
35
+ "prop-types": "^15.0.0",
36
+ "react-native-handlebars": "^5.0.0-alpha.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@applicaster/zapp-pipes-v2-client": "*",
@@ -6,7 +6,6 @@ import { deprecationMessage } from "../appUtils";
6
6
 
7
7
  import { pluginUtilsLogger } from "./logger";
8
8
  import { platformSelect } from "../reactUtils";
9
- import { get } from "../utils";
10
9
 
11
10
  type PluginModule = any;
12
11
  type Plugin = {
@@ -30,10 +29,7 @@ export function getComponentModule({
30
29
  components: ComponentsMap;
31
30
  plugins: Plugin[] | QuickBrickPlugin[];
32
31
  }) {
33
- const component = R.compose(
34
- R.prop(R.__, components),
35
- toPascalCase
36
- )(componentType);
32
+ const component = components[toPascalCase(componentType)];
37
33
 
38
34
  if (component) {
39
35
  return component;
@@ -60,7 +56,9 @@ export function findComponentByType({
60
56
  ? R.compose(...R.reverse(decorators))
61
57
  : decorators;
62
58
 
63
- const component = getComponentModule({ componentType, components, plugins });
59
+ const module = getComponentModule({ componentType, components, plugins });
60
+
61
+ const component = module?.Component || module;
64
62
 
65
63
  return R.unless(R.isNil, applyDecorators)(component);
66
64
  }
@@ -255,6 +253,3 @@ const getPluginType = R.pathOr("unknown_plugin_type", [
255
253
 
256
254
  export const isPlayerPlugin = (routeState): boolean =>
257
255
  getPluginType(routeState) === "player";
258
-
259
- export const getPluginModuleUrlScheme = (plugin) =>
260
- get(plugin, ["module", "urlScheme"]);
@@ -3,7 +3,7 @@ import { View } from "react-native";
3
3
  import * as R from "ramda";
4
4
 
5
5
  import { useNavigation } from "../navigation";
6
- import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
7
7
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
8
8
  import { dismissModal, openModal } from "../../modalState";
9
9
 
@@ -16,7 +16,7 @@ const ModalContainer = platformSelect({
16
16
 
17
17
  export function useAdvertisingInterstitial() {
18
18
  const { screenData, currentRoute } = useNavigation();
19
- const plugins = usePlugins();
19
+ const { plugins } = usePickFromState();
20
20
 
21
21
  return useEffect(() => {
22
22
  // TODD: typing problem: fix any type
@@ -1,5 +1,5 @@
1
1
  import EventEmitter from "events";
2
- import { renderHook, act } from "@testing-library/react-native";
2
+ import { renderHook, act } from "@testing-library/react-hooks";
3
3
  import { useAppState } from "../useAppState";
4
4
 
5
5
  const emitter = new EventEmitter();
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
 
3
3
  jest.mock(
4
4
  "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext",
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
 
3
- import { renderHook, act, waitFor } from "@testing-library/react-native";
3
+ import { renderHook } from "@testing-library/react-hooks";
4
+ import { act, waitFor } from "@testing-library/react-native";
4
5
  import { Provider } from "react-redux";
5
6
  import configureStore from "redux-mock-store";
6
7
  import { useTrackedView } from "../useTrackedView";
@@ -0,0 +1 @@
1
+ export { useIsCasting } from "./useIsCasting";
@@ -0,0 +1,57 @@
1
+ import React from "react";
2
+ import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
3
+ import { useAppState } from "@applicaster/zapp-react-native-utils/reactHooks/app";
4
+ import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
5
+
6
+ const CHROMECAST_IDENTIFIER = "quick-brick-chromecast-action";
7
+
8
+ const fakeEntry: any = {
9
+ title: "Chromecast use is casting fake entry",
10
+ id: "quick-brick-use-is-casting-fake-entry",
11
+ };
12
+
13
+ /**
14
+ * Returns the cast action state connection status, does not update when app is in background on Apple platforms
15
+ * On other platforms, it continues to check the cast action state even when the app is in background
16
+ */
17
+ export const useIsCasting = () => {
18
+ const actionContext = useActions(CHROMECAST_IDENTIFIER);
19
+ const appState = useAppState();
20
+ const isAppInForeground = appState === "active";
21
+ const shouldOnlyUpdateInForeground = isApplePlatform();
22
+
23
+ const [castActionState, setCastActionState] = React.useState(
24
+ !actionContext ? null : actionContext.initialEntryState(fakeEntry)
25
+ );
26
+
27
+ React.useEffect(() => {
28
+ if (!shouldOnlyUpdateInForeground || isAppInForeground) {
29
+ if (actionContext && castActionState === null) {
30
+ setCastActionState(actionContext.initialEntryState(fakeEntry));
31
+ }
32
+ }
33
+ }, [
34
+ actionContext,
35
+ setCastActionState,
36
+ isAppInForeground,
37
+ shouldOnlyUpdateInForeground,
38
+ ]);
39
+
40
+ React.useEffect(() => {
41
+ if (typeof actionContext?.addListener === "function") {
42
+ return actionContext?.addListener(String(fakeEntry.id), (state) => {
43
+ // Only check foreground state on Apple platforms
44
+ if (!shouldOnlyUpdateInForeground || isAppInForeground) {
45
+ setCastActionState(state);
46
+ }
47
+ });
48
+ }
49
+ }, [
50
+ setCastActionState,
51
+ actionContext,
52
+ isAppInForeground,
53
+ shouldOnlyUpdateInForeground,
54
+ ]);
55
+
56
+ return !!castActionState?.connected;
57
+ };
@@ -1,8 +1,10 @@
1
1
  import * as React from "react";
2
- import { cleanup, renderHook, waitFor } from "@testing-library/react-native";
2
+ import { cleanup, renderHook } from "@testing-library/react-hooks";
3
3
  import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
4
4
  import { ActionExecutorContext } from "@applicaster/zapp-react-native-utils/actionsExecutor/ActionExecutorContext";
5
5
 
6
+ import { waitFor } from "@testing-library/react-native";
7
+
6
8
  const mockNavigator = {
7
9
  getPathname: () => "pathnameMock",
8
10
  push: jest.fn(),
@@ -0,0 +1,55 @@
1
+ import * as React from "react";
2
+
3
+ const layoutReducer = (state, { payload }) => {
4
+ return state.map((item, index, _state) => ({
5
+ height: index === payload.index ? payload.height : item.height,
6
+ y:
7
+ index > 0
8
+ ? _state.slice(0, index).reduce((acc, value) => acc + value.height, 0)
9
+ : 0,
10
+ }));
11
+ };
12
+
13
+ export const useComponentsLayout = (count, onFinishLoadingVisible) => {
14
+ const [itemsLayout, dispatchItemLayout] = React.useReducer(
15
+ layoutReducer,
16
+ Array.from({ length: count }, () => ({ height: 0, y: 0 }))
17
+ );
18
+
19
+ const notified = React.useRef(false);
20
+ const [listHeight, setListHeight] = React.useState<number>(0);
21
+
22
+ const onItemLayout = React.useCallback(
23
+ (index) => (event) => {
24
+ const { height } = event.nativeEvent.layout;
25
+ dispatchItemLayout({ payload: { index, height } });
26
+ },
27
+ []
28
+ );
29
+
30
+ const onListLayout = React.useCallback((event) => {
31
+ const { height } = event.nativeEvent.layout;
32
+ setListHeight(height);
33
+ }, []);
34
+
35
+ React.useEffect(() => {
36
+ if (!notified.current) {
37
+ const finishLoadingVisible = !!itemsLayout.find(
38
+ (item) => item.y > listHeight
39
+ );
40
+
41
+ if (finishLoadingVisible) {
42
+ notified.current = true;
43
+ onFinishLoadingVisible?.();
44
+ }
45
+ }
46
+ }, [itemsLayout, listHeight]);
47
+
48
+ return React.useMemo(
49
+ () => ({
50
+ onItemLayout,
51
+ onListLayout,
52
+ }),
53
+ []
54
+ );
55
+ };
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable react/prop-types */
2
2
  import React from "react";
3
- import { renderHook, cleanup } from "@testing-library/react-native";
3
+ import { renderHook, cleanup } from "@testing-library/react-hooks";
4
4
  import { ConfigurationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfigutaionContext";
5
5
  import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
6
6
 
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { renderHook, cleanup } from "@testing-library/react-native";
2
+ import { renderHook, cleanup } from "@testing-library/react-hooks";
3
3
  import { NetworkStatusContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NetworkStatusContext";
4
4
 
5
5
  const MockNetInfo = {
@@ -27,20 +27,20 @@ describe("Debug utils", () => {
27
27
  it("should create new timer if timer with a label does not exist", () => {
28
28
  performanceNowMock.mockReturnValue(1000);
29
29
  time("timer1");
30
- expect(timers.timer1).toBeDefined();
31
- expect(timers.timer1.startTime).toBe(1000);
30
+ expect(timers["timer1"]).toBeDefined();
31
+ expect(timers["timer1"].startTime).toBe(1000);
32
32
  });
33
33
 
34
34
  it("should update start time of timer if timer with a label exists", () => {
35
35
  // First call to time()
36
36
  performanceNowMock.mockReturnValue(1000);
37
37
  time("timer1");
38
- const previousStartTime = timers.timer1.startTime;
38
+ const previousStartTime = timers["timer1"].startTime;
39
39
 
40
40
  // Second call to time()
41
41
  performanceNowMock.mockReturnValue(2000);
42
42
  time("timer1");
43
- const currentStartTime = timers.timer1.startTime;
43
+ const currentStartTime = timers["timer1"].startTime;
44
44
 
45
45
  expect(previousStartTime).toBe(1000);
46
46
  expect(currentStartTime).toBe(2000);
@@ -1,23 +1,28 @@
1
1
  /* eslint react-native/split-platform-components: off */
2
2
 
3
3
  import { Platform, PlatformIOSStatic, NativeModules } from "react-native";
4
+ import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
5
+ import { F as alwaysFalse } from "ramda";
4
6
  import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
5
7
 
6
- export const useIsTablet = (): boolean => {
7
- const platform = Platform.OS;
8
+ const useIsTabletIos = (): boolean => {
9
+ const { isPad } = Platform as PlatformIOSStatic;
8
10
 
9
- if (platform === "ios") {
10
- const { isPad } = Platform as PlatformIOSStatic;
11
-
12
- return Boolean(isPad);
13
- }
14
-
15
- if (platform === "android") {
16
- const initialProps =
17
- NativeModules.QuickBrickCommunicationModule?.initialProps;
11
+ return isPad;
12
+ };
18
13
 
19
- return toBooleanWithDefaultFalse(initialProps?.is_tablet);
20
- }
14
+ const useIsTabletAndroid = (): boolean => {
15
+ const { initialProps } = NativeModules.QuickBrickCommunicationModule;
21
16
 
22
- return false;
17
+ return toBooleanWithDefaultFalse(initialProps?.is_tablet);
23
18
  };
19
+
20
+ export const useIsTablet = platformSelect({
21
+ ios: useIsTabletIos,
22
+ android: useIsTabletAndroid,
23
+ lg_tv: alwaysFalse,
24
+ samsung_tv: alwaysFalse,
25
+ android_tv: alwaysFalse,
26
+ tvos: alwaysFalse,
27
+ default: alwaysFalse,
28
+ });
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
3
  import { useIsTablet } from "./useIsTablet";
3
- import { useAppData } from "@applicaster/zapp-react-native-redux";
4
4
 
5
5
  export const useMemoizedIsTablet = () => {
6
6
  const isTablet = useIsTablet();
@@ -14,9 +14,9 @@ export const useMemoizedIsTablet = () => {
14
14
  };
15
15
 
16
16
  export const useIsTabletLandscape = (): boolean => {
17
- const { isTabletPortrait } = useAppData();
17
+ const { appData } = usePickFromState(["appData"]);
18
18
 
19
19
  const isTablet = useIsTablet();
20
20
 
21
- return isTablet && !isTabletPortrait;
21
+ return isTablet && !appData.isTabletPortrait;
22
22
  };