@applicaster/zapp-react-native-utils 15.0.0-rc.14 → 15.0.0-rc.141
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/README.md +0 -6
- package/actionUtils/index.ts +7 -0
- package/actionsExecutor/ActionExecutorContext.tsx +86 -12
- package/actionsExecutor/feedDecorator.ts +6 -6
- package/adsUtils/__tests__/createVMAP.test.ts +419 -0
- package/adsUtils/index.ts +2 -2
- package/analyticsUtils/README.md +1 -1
- package/analyticsUtils/analyticsMapper.ts +10 -2
- package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
- package/appUtils/HooksManager/index.ts +45 -10
- package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
- package/appUtils/accessibilityManager/__tests__/utils.test.ts +360 -0
- package/appUtils/accessibilityManager/const.ts +4 -0
- package/appUtils/accessibilityManager/hooks.ts +20 -13
- package/appUtils/accessibilityManager/index.ts +28 -1
- package/appUtils/accessibilityManager/utils.ts +59 -8
- package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
- package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
- package/appUtils/contextKeysManager/contextResolver.ts +51 -22
- package/appUtils/contextKeysManager/index.ts +65 -10
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +3 -0
- package/appUtils/focusManager/index.ios.ts +43 -4
- package/appUtils/focusManager/treeDataStructure/Tree/__tests__/Tree.test.js +46 -0
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +18 -18
- package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
- package/appUtils/focusManagerAux/utils/index.ts +13 -7
- package/appUtils/focusManagerAux/utils/utils.ios.ts +202 -3
- package/appUtils/keyCodes/keys/keys.web.ts +1 -4
- package/appUtils/localizationsHelper.ts +4 -0
- package/appUtils/orientationHelper.ts +2 -4
- package/appUtils/platform/platformUtils.ts +117 -18
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
- package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
- package/appUtils/playerManager/index.ts +9 -0
- package/appUtils/playerManager/player.ts +5 -1
- package/appUtils/playerManager/playerNative.ts +31 -17
- package/appUtils/playerManager/usePlayer.tsx +5 -3
- package/appUtils/playerManager/usePlayerState.tsx +14 -2
- package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
- package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
- package/arrayUtils/index.ts +5 -0
- package/cellUtils/__tests__/cellUtils.test.ts +39 -0
- package/cellUtils/index.ts +43 -1
- package/cloudEventsUtils/__tests__/index.test.ts +529 -0
- package/cloudEventsUtils/index.ts +65 -1
- package/componentsUtils/index.ts +8 -0
- package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +38 -0
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
- package/configurationUtils/index.ts +17 -11
- package/dateUtils/__tests__/dayjs.test.ts +327 -0
- package/dateUtils/index.ts +2 -0
- package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
- package/errorUtils/__tests__/GeneralError.test.ts +97 -0
- package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
- package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
- package/errorUtils/__tests__/NetworkError.test.ts +202 -0
- package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
- package/errorUtils/__tests__/invariant.test.ts +112 -0
- package/focusManager/aux/index.ts +1 -1
- package/headersUtils/__tests__/headersUtils.test.js +11 -1
- package/headersUtils/index.ts +2 -1
- package/manifestUtils/_internals/__tests__/index.test.js +41 -0
- package/manifestUtils/_internals/index.js +33 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +115 -11
- package/manifestUtils/fieldUtils/__tests__/fieldUtils.test.js +49 -0
- package/manifestUtils/fieldUtils/index.js +54 -0
- package/manifestUtils/index.js +2 -0
- package/manifestUtils/keys.js +249 -0
- package/manifestUtils/mobileAction/button/__tests__/mobileActionButton.test.js +168 -0
- package/manifestUtils/mobileAction/button/index.js +140 -0
- package/manifestUtils/mobileAction/container/__tests__/mobileActionButtonsContainer.test.js +102 -0
- package/manifestUtils/mobileAction/container/index.js +73 -0
- package/manifestUtils/mobileAction/groups/__tests__/buildMobileActionButtonGroups.test.js +127 -0
- package/manifestUtils/mobileAction/groups/defaults.js +76 -0
- package/manifestUtils/mobileAction/groups/index.js +80 -0
- package/manifestUtils/platformIsTV.js +13 -0
- package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
- package/manifestUtils/tvAction/container/index.js +1 -1
- package/navigationUtils/index.ts +15 -5
- package/numberUtils/__tests__/toNumber.test.ts +27 -0
- package/numberUtils/__tests__/toPositiveNumber.test.ts +193 -0
- package/numberUtils/index.ts +23 -1
- package/package.json +4 -4
- package/playerUtils/usePlayerTTS.ts +8 -3
- package/pluginUtils/index.ts +4 -0
- package/reactHooks/advertising/index.ts +2 -2
- package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
- package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
- package/reactHooks/cell-click/__tests__/index.test.js +1 -3
- package/reactHooks/cell-click/index.ts +2 -1
- package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
- package/reactHooks/connection/__tests__/index.test.js +1 -1
- package/reactHooks/debugging/__tests__/index.test.js +4 -4
- package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
- package/reactHooks/device/useIsTablet.tsx +14 -19
- package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
- package/reactHooks/events/index.ts +20 -0
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
- package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
- package/reactHooks/feed/__tests__/{useInflatedUrl.test.ts → useInflatedUrl.test.tsx} +62 -7
- package/reactHooks/feed/index.ts +0 -2
- package/reactHooks/feed/useBatchLoading.ts +7 -1
- package/reactHooks/feed/useEntryScreenId.ts +2 -2
- package/reactHooks/feed/useInflatedUrl.ts +44 -18
- package/reactHooks/feed/usePipesCacheReset.ts +3 -1
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
- package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +12 -8
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/index.test.tsx +1 -1
- package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
- package/reactHooks/layout/index.ts +1 -1
- package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
- package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
- package/reactHooks/navigation/__tests__/index.test.tsx +40 -9
- package/reactHooks/navigation/index.ts +27 -11
- package/reactHooks/navigation/useRoute.ts +11 -7
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
- package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
- package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
- package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
- package/reactHooks/resolvers/useCellResolver.ts +6 -2
- package/reactHooks/resolvers/useComponentResolver.ts +19 -3
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
- package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
- package/reactHooks/screen/useTargetScreenData.ts +4 -2
- package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
- package/reactHooks/state/index.ts +2 -0
- package/reactHooks/state/useComponentScreenState.ts +45 -0
- package/reactHooks/state/useRefWithInitialValue.ts +10 -0
- package/reactHooks/state/useRivers.ts +1 -1
- package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
- package/reactHooks/usePluginConfiguration.ts +2 -2
- package/reactHooks/utils/__tests__/index.test.js +1 -1
- package/rectUtils/__tests__/index.test.ts +549 -0
- package/rectUtils/index.ts +2 -2
- package/refreshUtils/RefreshCoordinator/__tests__/refreshCoordinator.test.ts +206 -0
- package/refreshUtils/RefreshCoordinator/index.ts +245 -0
- package/refreshUtils/RefreshCoordinator/utils/__tests__/getDataRefreshConfig.test.ts +104 -0
- package/refreshUtils/RefreshCoordinator/utils/index.ts +29 -0
- package/screenPickerUtils/__tests__/index.test.ts +333 -0
- package/screenPickerUtils/index.ts +5 -0
- package/screenState/__tests__/index.test.ts +1 -1
- package/screenUtils/index.ts +3 -0
- package/searchUtils/const.ts +7 -0
- package/searchUtils/index.ts +3 -0
- package/services/storageServiceSync.web.ts +1 -1
- package/stringUtils/index.ts +1 -1
- package/testUtils/index.tsx +30 -21
- package/time/__tests__/BackgroundTimer.test.ts +156 -0
- package/time/__tests__/Timer.test.ts +236 -0
- package/typeGuards/__tests__/isString.test.ts +21 -0
- package/typeGuards/index.ts +4 -0
- package/utils/__tests__/clone.test.ts +158 -0
- package/utils/__tests__/mapAccum.test.ts +73 -0
- package/utils/__tests__/mergeRight.test.ts +48 -0
- package/utils/__tests__/path.test.ts +7 -0
- package/utils/__tests__/selectors.test.ts +124 -0
- package/utils/clone.ts +7 -0
- package/utils/index.ts +21 -1
- package/utils/mapAccum.ts +23 -0
- package/utils/mergeRight.ts +5 -0
- package/utils/path.ts +6 -3
- package/utils/pathOr.ts +5 -1
- package/utils/selectors.ts +46 -0
- package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +49 -12
- package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
- package/reactHooks/componentsMap/index.ts +0 -55
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +0 -75
- package/reactHooks/feed/useFeedRefresh.tsx +0 -65
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const { mobileActionButtonsContainer } = require("../container");
|
|
2
|
+
const { mobileActionButton } = require("../button");
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
DEFAULT_MOBILE_ACTION_BUTTONS_CONTAINER_DEFAULTS,
|
|
6
|
+
DEFAULT_MOBILE_ACTION_BUTTON_SHARED_DEFAULTS,
|
|
7
|
+
DEFAULT_MOBILE_ACTION_BUTTON_PRESETS,
|
|
8
|
+
} = require("./defaults");
|
|
9
|
+
|
|
10
|
+
const CONTAINER_GROUP_LABEL = "Mobile Buttons Container"; // NOTE: used as key – "Mobile Buttons Container" -> "mobile_buttons_container"
|
|
11
|
+
|
|
12
|
+
const CONTAINER_GROUP_DESCRIPTION =
|
|
13
|
+
"Configuration for mobile action buttons container";
|
|
14
|
+
|
|
15
|
+
const BUTTON_GROUPS = [
|
|
16
|
+
{
|
|
17
|
+
index: 1,
|
|
18
|
+
label: "Mobile Button 1",
|
|
19
|
+
description: "Primary mobile action button",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
index: 2,
|
|
23
|
+
label: "Mobile Button 2",
|
|
24
|
+
description: "Secondary mobile action button",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
index: 3,
|
|
28
|
+
label: "Mobile Button 3",
|
|
29
|
+
description: "Tertiary mobile action button",
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Builds the shared mobile action button manifest groups while letting each
|
|
35
|
+
* plugin supply only its supported insertion positions and explicit overrides.
|
|
36
|
+
*
|
|
37
|
+
* @param {object} options
|
|
38
|
+
* @param {object} [options.containerDefaults={}]
|
|
39
|
+
* @param {object} [options.sharedButtonDefaults={}]
|
|
40
|
+
* @param {Record<number, object>} [options.buttonOverrides={}]
|
|
41
|
+
* @returns {object[]}
|
|
42
|
+
*/
|
|
43
|
+
function buildMobileActionButtonGroups({
|
|
44
|
+
containerDefaults = {},
|
|
45
|
+
sharedButtonDefaults = {},
|
|
46
|
+
buttonOverrides = {},
|
|
47
|
+
}) {
|
|
48
|
+
const groups = [
|
|
49
|
+
mobileActionButtonsContainer({
|
|
50
|
+
label: CONTAINER_GROUP_LABEL,
|
|
51
|
+
description: CONTAINER_GROUP_DESCRIPTION,
|
|
52
|
+
defaults: {
|
|
53
|
+
...DEFAULT_MOBILE_ACTION_BUTTONS_CONTAINER_DEFAULTS,
|
|
54
|
+
...containerDefaults,
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
BUTTON_GROUPS.forEach(({ index, label, description }) => {
|
|
60
|
+
groups.push(
|
|
61
|
+
mobileActionButton({
|
|
62
|
+
isFirstButton: index === 1,
|
|
63
|
+
label,
|
|
64
|
+
description,
|
|
65
|
+
defaults: {
|
|
66
|
+
...DEFAULT_MOBILE_ACTION_BUTTON_SHARED_DEFAULTS,
|
|
67
|
+
...sharedButtonDefaults,
|
|
68
|
+
...DEFAULT_MOBILE_ACTION_BUTTON_PRESETS[index],
|
|
69
|
+
...(buttonOverrides[index] || {}),
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return groups;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
buildMobileActionButtonGroups,
|
|
80
|
+
};
|
|
@@ -38,7 +38,7 @@ function tvActionButtonsContainer({ label, description, defaults }) {
|
|
|
38
38
|
generateFieldsFromDefaultsWithoutPrefixedLabel(
|
|
39
39
|
label,
|
|
40
40
|
defaults,
|
|
41
|
-
tvActionButtonContainerFields(defaults
|
|
41
|
+
tvActionButtonContainerFields(defaults.position)
|
|
42
42
|
)
|
|
43
43
|
);
|
|
44
44
|
|
package/navigationUtils/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { layoutV2TypeMatcher } from "./layoutV2TypeMatcher";
|
|
|
5
5
|
import { HOOKS_EVENTS } from "../appUtils/HooksManager/constants";
|
|
6
6
|
import { HooksManager } from "../appUtils/HooksManager";
|
|
7
7
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
import { zappHookModalStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ZappHookModalContext";
|
|
9
10
|
import { logger } from "@applicaster/zapp-react-native-utils/logger";
|
|
10
11
|
import {
|
|
11
12
|
isGeneralPlugin,
|
|
@@ -15,6 +16,8 @@ import {
|
|
|
15
16
|
} from "./itemTypeMatchers";
|
|
16
17
|
import { RootState } from "@applicaster/zapp-react-native-redux/store";
|
|
17
18
|
|
|
19
|
+
import { pick } from "@applicaster/zapp-react-native-utils/utils";
|
|
20
|
+
|
|
18
21
|
type PathAttribute = {
|
|
19
22
|
screenType: string;
|
|
20
23
|
screenId: string;
|
|
@@ -403,15 +406,22 @@ export const mapContentTypesToRivers = (
|
|
|
403
406
|
};
|
|
404
407
|
|
|
405
408
|
export const runZappHooksForEntry = async (
|
|
406
|
-
entry: HookPluginProps["payload"]
|
|
407
|
-
|
|
409
|
+
entry: HookPluginProps["payload"]
|
|
410
|
+
): Promise<{ success: boolean; payload: ZappEntry }> => {
|
|
411
|
+
const {
|
|
408
412
|
setState,
|
|
409
413
|
resetState,
|
|
410
414
|
setIsHooksExecutionInProgress,
|
|
411
415
|
setIsPresentingFullScreen,
|
|
412
416
|
setIsRunningInBackground,
|
|
413
|
-
}
|
|
414
|
-
|
|
417
|
+
} = pick(zappHookModalStore.getState(), [
|
|
418
|
+
"setState",
|
|
419
|
+
"resetState",
|
|
420
|
+
"setIsHooksExecutionInProgress",
|
|
421
|
+
"setIsPresentingFullScreen",
|
|
422
|
+
"setIsRunningInBackground",
|
|
423
|
+
]);
|
|
424
|
+
|
|
415
425
|
resetState?.();
|
|
416
426
|
|
|
417
427
|
let success;
|
|
@@ -24,6 +24,8 @@ describe("toNumber", () => {
|
|
|
24
24
|
it("return undefined if input is not a number", () => {
|
|
25
25
|
const inputs = [
|
|
26
26
|
"vfdvf",
|
|
27
|
+
"5n",
|
|
28
|
+
"-5n",
|
|
27
29
|
null,
|
|
28
30
|
undefined,
|
|
29
31
|
NaN,
|
|
@@ -41,4 +43,29 @@ describe("toNumber", () => {
|
|
|
41
43
|
expect(output).toBeUndefined();
|
|
42
44
|
});
|
|
43
45
|
});
|
|
46
|
+
|
|
47
|
+
describe("BigInt support", () => {
|
|
48
|
+
// Conditional test based on BigInt availability
|
|
49
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
50
|
+
|
|
51
|
+
if (isBigIntSupported) {
|
|
52
|
+
it("converts BigInt to number when BigInt is supported", () => {
|
|
53
|
+
expect(toNumber(BigInt(5))).toBe(5);
|
|
54
|
+
expect(toNumber(BigInt(0))).toBe(0);
|
|
55
|
+
expect(toNumber(BigInt(-10))).toBe(-10);
|
|
56
|
+
expect(toNumber(BigInt(1000))).toBe(1000);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("handles large BigInt values that may lose precision", () => {
|
|
60
|
+
const largeBigInt = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1);
|
|
61
|
+
const result = toNumber(largeBigInt);
|
|
62
|
+
expect(result).toBe(Number(largeBigInt));
|
|
63
|
+
});
|
|
64
|
+
} else {
|
|
65
|
+
it("skips BigInt tests when BigInt is not supported", () => {
|
|
66
|
+
// Placeholder test to indicate BigInt is not available
|
|
67
|
+
expect(typeof BigInt).toBe("undefined");
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
44
71
|
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { toPositiveNumber } from "..";
|
|
2
|
+
|
|
3
|
+
describe("toPositiveNumber", () => {
|
|
4
|
+
describe("valid positive numbers", () => {
|
|
5
|
+
it("returns the number for positive integers", () => {
|
|
6
|
+
expect(toPositiveNumber(5)).toBe(5);
|
|
7
|
+
expect(toPositiveNumber(1000)).toBe(1000);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("returns the number for positive floats", () => {
|
|
11
|
+
expect(toPositiveNumber(0.1)).toBe(0.1);
|
|
12
|
+
expect(toPositiveNumber(3.14159)).toBe(3.14159);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("returns the number for very small positive numbers", () => {
|
|
16
|
+
expect(toPositiveNumber(1e-300)).toBe(1e-300);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("returns the number for very large positive numbers", () => {
|
|
20
|
+
expect(toPositiveNumber(1e300)).toBe(1e300);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("returns Infinity for positive infinity", () => {
|
|
24
|
+
expect(toPositiveNumber(Infinity)).toBe(Infinity);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("converts valid positive strings to numbers", () => {
|
|
28
|
+
expect(toPositiveNumber("5")).toBe(5);
|
|
29
|
+
expect(toPositiveNumber("3.14")).toBe(3.14);
|
|
30
|
+
expect(toPositiveNumber(" 100 ")).toBe(100);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("converts boolean true to undefined", () => {
|
|
34
|
+
expect(toPositiveNumber(true)).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("converts single-element arrays to undefined", () => {
|
|
38
|
+
expect(toPositiveNumber([5])).toBeUndefined();
|
|
39
|
+
expect(toPositiveNumber(["10"])).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("invalid cases (return undefined)", () => {
|
|
44
|
+
describe("zero values", () => {
|
|
45
|
+
it("returns undefined for zero", () => {
|
|
46
|
+
expect(toPositiveNumber(0)).toBeUndefined();
|
|
47
|
+
expect(toPositiveNumber(-0)).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("returns undefined for string zero", () => {
|
|
51
|
+
expect(toPositiveNumber("0")).toBeUndefined();
|
|
52
|
+
expect(toPositiveNumber(" 0 ")).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns undefined for boolean false", () => {
|
|
56
|
+
expect(toPositiveNumber(false)).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("returns undefined for empty arrays", () => {
|
|
60
|
+
expect(toPositiveNumber([])).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns undefined for empty strings", () => {
|
|
64
|
+
expect(toPositiveNumber("")).toBeUndefined();
|
|
65
|
+
expect(toPositiveNumber(" ")).toBeUndefined();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("negative values", () => {
|
|
70
|
+
it("returns undefined for negative numbers", () => {
|
|
71
|
+
expect(toPositiveNumber(-5)).toBeUndefined();
|
|
72
|
+
expect(toPositiveNumber(-0.1)).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("returns undefined for negative strings", () => {
|
|
76
|
+
expect(toPositiveNumber("-5")).toBeUndefined();
|
|
77
|
+
expect(toPositiveNumber(" -10 ")).toBeUndefined();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("returns undefined for negative infinity", () => {
|
|
81
|
+
expect(toPositiveNumber(-Infinity)).toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("non-convertible values", () => {
|
|
86
|
+
it("returns undefined for null", () => {
|
|
87
|
+
expect(toPositiveNumber(null)).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("returns undefined for undefined", () => {
|
|
91
|
+
expect(toPositiveNumber(undefined)).toBeUndefined();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns undefined for objects", () => {
|
|
95
|
+
expect(toPositiveNumber({})).toBeUndefined();
|
|
96
|
+
expect(toPositiveNumber({ a: 1 })).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("returns undefined for multi-element arrays", () => {
|
|
100
|
+
expect(toPositiveNumber([1, 2])).toBeUndefined();
|
|
101
|
+
expect(toPositiveNumber(["a", "b"])).toBeUndefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("returns undefined for non-numeric strings", () => {
|
|
105
|
+
expect(toPositiveNumber("abc")).toBeUndefined();
|
|
106
|
+
expect(toPositiveNumber("5px")).toBeUndefined();
|
|
107
|
+
expect(toPositiveNumber("123.45.67")).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("returns undefined for NaN", () => {
|
|
111
|
+
expect(toPositiveNumber(NaN)).toBeUndefined();
|
|
112
|
+
expect(toPositiveNumber(Number("abc"))).toBeUndefined();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("special cases", () => {
|
|
118
|
+
it("handles exponential notation correctly", () => {
|
|
119
|
+
expect(toPositiveNumber("1e5")).toBe(100000);
|
|
120
|
+
expect(toPositiveNumber("1e-5")).toBe(0.00001);
|
|
121
|
+
expect(toPositiveNumber("-1e5")).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("preserves precision for decimal numbers", () => {
|
|
125
|
+
expect(toPositiveNumber(0.1 + 0.2)).toBeCloseTo(0.3);
|
|
126
|
+
expect(toPositiveNumber("0.1")).toBe(0.1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("handles numeric strings with leading zeros", () => {
|
|
130
|
+
expect(toPositiveNumber("005")).toBe(5);
|
|
131
|
+
expect(toPositiveNumber("0.5")).toBe(0.5);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("returns undefined for numeric strings with trailing non-numeric characters", () => {
|
|
135
|
+
expect(toPositiveNumber("5px")).toBeUndefined();
|
|
136
|
+
expect(toPositiveNumber("10%")).toBeUndefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("handles scientific notation correctly", () => {
|
|
140
|
+
expect(toPositiveNumber("1.5e2")).toBe(150);
|
|
141
|
+
expect(toPositiveNumber("-2.5e3")).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe("type conversion behavior", () => {
|
|
146
|
+
it("converts Date objects correctly", () => {
|
|
147
|
+
const date = new Date(2026, 1, 17);
|
|
148
|
+
expect(toPositiveNumber(date)).toBeUndefined();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("converts functions to NaN (returns undefined)", () => {
|
|
152
|
+
expect(toPositiveNumber(() => {})).toBeUndefined();
|
|
153
|
+
expect(toPositiveNumber(Math.sqrt)).toBeUndefined();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("handles Symbol values", () => {
|
|
157
|
+
expect(toPositiveNumber(Symbol("test"))).toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("BigInt support", () => {
|
|
162
|
+
// Conditional test based on BigInt availability
|
|
163
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
164
|
+
|
|
165
|
+
if (isBigIntSupported) {
|
|
166
|
+
it("converts positive BigInt values to numbers when BigInt is supported", () => {
|
|
167
|
+
expect(toPositiveNumber(BigInt(5))).toBe(5);
|
|
168
|
+
expect(toPositiveNumber(BigInt(100))).toBe(100);
|
|
169
|
+
expect(toPositiveNumber(BigInt(1000))).toBe(1000);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("returns undefined for zero BigInt", () => {
|
|
173
|
+
expect(toPositiveNumber(BigInt(0))).toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("returns undefined for negative BigInt values", () => {
|
|
177
|
+
expect(toPositiveNumber(BigInt(-5))).toBeUndefined();
|
|
178
|
+
expect(toPositiveNumber(BigInt(-100))).toBeUndefined();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("handles large positive BigInt values", () => {
|
|
182
|
+
const largeBigInt = BigInt(Number.MAX_SAFE_INTEGER);
|
|
183
|
+
const result = toPositiveNumber(largeBigInt);
|
|
184
|
+
expect(result).toBe(Number(largeBigInt));
|
|
185
|
+
});
|
|
186
|
+
} else {
|
|
187
|
+
it("skips BigInt tests when BigInt is not supported", () => {
|
|
188
|
+
// Placeholder test to indicate BigInt is not available
|
|
189
|
+
expect(typeof BigInt).toBe("undefined");
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
package/numberUtils/index.ts
CHANGED
|
@@ -8,7 +8,11 @@ export const toNumber = (value: unknown): number | undefined => {
|
|
|
8
8
|
return undefined;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// Feature-detect BigInt support to avoid ReferenceError on older runtimes
|
|
12
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
13
|
+
const isBigIntValue = isBigIntSupported && R.is(BigInt, value);
|
|
14
|
+
|
|
15
|
+
if (R.is(Number, value) || isBigIntValue || R.is(String, value)) {
|
|
12
16
|
const numberOrNan = Number(value);
|
|
13
17
|
|
|
14
18
|
return Number.isNaN(numberOrNan) ? undefined : numberOrNan;
|
|
@@ -69,6 +73,24 @@ export const isMinusZero = (value: number) => {
|
|
|
69
73
|
return 1 / value === -Infinity;
|
|
70
74
|
};
|
|
71
75
|
|
|
76
|
+
export const toPositiveNumber = (value: unknown): number | undefined => {
|
|
77
|
+
const possibleNumber = toNumber(value);
|
|
78
|
+
|
|
79
|
+
if (R.isNil(possibleNumber)) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (possibleNumber < 0) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isZero(possibleNumber)) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return possibleNumber;
|
|
92
|
+
};
|
|
93
|
+
|
|
72
94
|
export const toPositiveNumberWithDefault = (
|
|
73
95
|
defaultValue: number,
|
|
74
96
|
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.
|
|
3
|
+
"version": "15.0.0-rc.141",
|
|
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.
|
|
30
|
+
"@applicaster/applicaster-types": "15.0.0-rc.141",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
34
|
+
"handlebars": "4.7.9",
|
|
34
35
|
"memoizee": "0.4.15",
|
|
35
|
-
"prop-types": "^15.0.0"
|
|
36
|
-
"react-native-handlebars": "^5.0.0-alpha.1"
|
|
36
|
+
"prop-types": "^15.0.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@applicaster/zapp-pipes-v2-client": "*",
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useAccessibilityManager,
|
|
5
|
+
useAccessibilityState,
|
|
6
|
+
} from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
|
|
4
7
|
import { PlayerTTS } from "@applicaster/zapp-react-native-utils/playerUtils/PlayerTTS";
|
|
5
8
|
|
|
6
9
|
export const usePlayerTTS = () => {
|
|
7
10
|
const player = usePlayer();
|
|
8
11
|
const accessibilityManager = useAccessibilityManager({});
|
|
12
|
+
const accessibilityState = useAccessibilityState();
|
|
13
|
+
const isScreenReaderEnabled = accessibilityState.screenReaderEnabled;
|
|
9
14
|
|
|
10
15
|
React.useEffect(() => {
|
|
11
|
-
if (player && accessibilityManager) {
|
|
16
|
+
if (player && accessibilityManager && isScreenReaderEnabled) {
|
|
12
17
|
const playerTTS = new PlayerTTS(player, accessibilityManager);
|
|
13
18
|
const unsubscribe = playerTTS.init();
|
|
14
19
|
|
|
@@ -17,5 +22,5 @@ export const usePlayerTTS = () => {
|
|
|
17
22
|
playerTTS.destroy();
|
|
18
23
|
};
|
|
19
24
|
}
|
|
20
|
-
}, [player, accessibilityManager]);
|
|
25
|
+
}, [player, accessibilityManager, isScreenReaderEnabled]);
|
|
21
26
|
};
|
package/pluginUtils/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { deprecationMessage } from "../appUtils";
|
|
|
6
6
|
|
|
7
7
|
import { pluginUtilsLogger } from "./logger";
|
|
8
8
|
import { platformSelect } from "../reactUtils";
|
|
9
|
+
import { get } from "../utils";
|
|
9
10
|
|
|
10
11
|
type PluginModule = any;
|
|
11
12
|
type Plugin = {
|
|
@@ -254,3 +255,6 @@ const getPluginType = R.pathOr("unknown_plugin_type", [
|
|
|
254
255
|
|
|
255
256
|
export const isPlayerPlugin = (routeState): boolean =>
|
|
256
257
|
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 {
|
|
6
|
+
import { usePlugins } 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
|
|
19
|
+
const plugins = usePlugins();
|
|
20
20
|
|
|
21
21
|
return useEffect(() => {
|
|
22
22
|
// TODD: typing problem: fix any type
|