@applicaster/zapp-react-native-utils 13.0.0-alpha.3755455151 → 13.0.0-alpha.4097222141
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/actionsExecutor/ActionExecutor.ts +16 -9
- package/actionsExecutor/ActionExecutorContext.tsx +59 -8
- package/alertUtils/alert.ts +148 -0
- package/alertUtils/index.ts +1 -148
- package/appUtils/HooksManager/Hook.ts +2 -2
- package/appUtils/HooksManager/types.ts +5 -2
- package/appUtils/contextKeysManager/contextResolver.ts +77 -0
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +1 -0
- package/appUtils/focusManager/index.ts +11 -3
- package/appUtils/focusManagerAux/utils/index.ts +4 -3
- package/appUtils/platform/const.ts +14 -0
- package/appUtils/platform/platformUtils.ts +47 -4
- package/appUtils/playerManager/player.ts +2 -2
- package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
- package/idleUtils/index.ts +1 -1
- package/idleUtils/withTimeout.ts +15 -2
- package/logger/const.ts +9 -67
- package/manifestUtils/__tests__/createConfig.test.js +0 -2
- package/navigationUtils/index.ts +3 -3
- package/numberUtils/index.ts +7 -5
- package/package.json +2 -2
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +5 -7
- package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
- package/reactHooks/cell-click/__tests__/index.test.js +5 -0
- package/reactHooks/cell-click/index.ts +7 -1
- package/reactHooks/feed/useFeedLoader.tsx +1 -1
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +1 -1
- package/reactHooks/layout/useDimensions/useDimensions.ts +8 -0
- package/reactHooks/navigation/useGetTabBarHeight.ts +1 -3
- package/reactHooks/state/useRefWithInitialValue.ts +14 -0
- package/reactHooks/state/useStateFromSubscribe.ts +23 -0
- package/reactHooks/usePluginConfiguration.ts +1 -1
- package/reactHooks/useSubscriberFor.ts +4 -3
- package/screenState/index.ts +24 -10
- package/theme/index.ts +1 -1
- package/time/Timer.ts +5 -2
- package/types.ts +1 -0
- package/zappFrameworkUtils/presentPluginOneTime.ts +2 -3
|
@@ -23,3 +23,17 @@ export const PLATFORMS = {
|
|
|
23
23
|
export const PLATFORM_KEYS = {
|
|
24
24
|
deviceClosedCaptioningEnabled: "device_closed_captioning_enabled",
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
export enum ZappPlatform {
|
|
28
|
+
Android = "android",
|
|
29
|
+
AndroidTV = "android_tv",
|
|
30
|
+
AmazonFireTV = "amazon",
|
|
31
|
+
iOS = "ios",
|
|
32
|
+
tvOS = "tvos",
|
|
33
|
+
Roku = "roku",
|
|
34
|
+
Tizen = "tizen",
|
|
35
|
+
Web = "web",
|
|
36
|
+
WebOS = "webos",
|
|
37
|
+
Vizio = "vizio",
|
|
38
|
+
Unknown = "unknown",
|
|
39
|
+
}
|
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
isSamsungPlatform,
|
|
7
7
|
} from "@applicaster/zapp-react-dom-app/App/Loader/utils/platform";
|
|
8
8
|
|
|
9
|
-
import { PLATFORM_KEYS, PLATFORMS } from "./const";
|
|
9
|
+
import { PLATFORM_KEYS, PLATFORMS, ZappPlatform } from "./const";
|
|
10
10
|
import { createLogger, utilsLogger } from "../../logger";
|
|
11
|
+
import { getPlatform } from "../../reactUtils";
|
|
12
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
11
13
|
|
|
12
14
|
const { log_debug } = createLogger({
|
|
13
15
|
category: "General",
|
|
@@ -15,6 +17,20 @@ const { log_debug } = createLogger({
|
|
|
15
17
|
parent: utilsLogger,
|
|
16
18
|
});
|
|
17
19
|
|
|
20
|
+
export const getZappPlatform = (): ZappPlatform => {
|
|
21
|
+
const platform = appStore.get("appData")?.platform;
|
|
22
|
+
|
|
23
|
+
switch (platform) {
|
|
24
|
+
case "amazon_fire_tv":
|
|
25
|
+
return ZappPlatform.AmazonFireTV;
|
|
26
|
+
case ZappPlatform.Vizio:
|
|
27
|
+
return ZappPlatform.Vizio;
|
|
28
|
+
default:
|
|
29
|
+
// TODO: Use only ZappPlatform enum
|
|
30
|
+
return getPlatform() as ZappPlatform;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
18
34
|
export const getUserAgent = () => window?.navigator?.userAgent;
|
|
19
35
|
|
|
20
36
|
/** VIZIO UTILS */
|
|
@@ -61,13 +77,22 @@ export class ClosedCaptioningManager {
|
|
|
61
77
|
|
|
62
78
|
private constructor() {
|
|
63
79
|
this.initialize();
|
|
80
|
+
|
|
81
|
+
window["vizioDebug"] = {
|
|
82
|
+
setCCEnabled: (isCCEnabled: boolean) => {
|
|
83
|
+
this.ccState$.next(isCCEnabled);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
64
86
|
}
|
|
65
87
|
|
|
66
88
|
static getInstance(): ClosedCaptioningManager {
|
|
67
89
|
if (!ClosedCaptioningManager.ccManagerInstance) {
|
|
90
|
+
log_debug("ClosedCaptioningManager: Creating new instance");
|
|
68
91
|
ClosedCaptioningManager.ccManagerInstance = new ClosedCaptioningManager();
|
|
69
92
|
}
|
|
70
93
|
|
|
94
|
+
log_debug("ClosedCaptioningManager: Returning existing instance");
|
|
95
|
+
|
|
71
96
|
return ClosedCaptioningManager.ccManagerInstance;
|
|
72
97
|
}
|
|
73
98
|
|
|
@@ -76,23 +101,41 @@ export class ClosedCaptioningManager {
|
|
|
76
101
|
PLATFORM_KEYS.deviceClosedCaptioningEnabled
|
|
77
102
|
);
|
|
78
103
|
|
|
79
|
-
log_debug("Initializing closed captioning manager", { existingState });
|
|
80
|
-
|
|
81
104
|
if (existingState !== null) {
|
|
105
|
+
log_debug(
|
|
106
|
+
`ClosedCaptioningManager: Setting initial state to ${existingState}`
|
|
107
|
+
);
|
|
108
|
+
|
|
82
109
|
this.ccState$.next(existingState === "true" || existingState === true);
|
|
110
|
+
} else {
|
|
111
|
+
log_debug("ClosedCaptioningManager: No existing state found");
|
|
83
112
|
}
|
|
84
113
|
|
|
85
114
|
if (hasVizioAPIs()) {
|
|
115
|
+
log_debug("ClosedCaptioningManager: Setting closed captioning handler");
|
|
116
|
+
|
|
86
117
|
window.VIZIO!.setClosedCaptionHandler((isCCEnabled) => {
|
|
87
|
-
log_debug(
|
|
118
|
+
log_debug(
|
|
119
|
+
"ClosedCaptioningManager: There was a change in the CC state",
|
|
120
|
+
{ isCCEnabled }
|
|
121
|
+
);
|
|
88
122
|
|
|
89
123
|
sessionStorage.setItem(
|
|
90
124
|
PLATFORM_KEYS.deviceClosedCaptioningEnabled,
|
|
91
125
|
isCCEnabled
|
|
92
126
|
);
|
|
93
127
|
|
|
128
|
+
log_debug(
|
|
129
|
+
"ClosedCaptioningManager: Saved CC state to session storage",
|
|
130
|
+
{ isCCEnabled }
|
|
131
|
+
);
|
|
132
|
+
|
|
94
133
|
this.ccState$.next(isCCEnabled);
|
|
95
134
|
});
|
|
135
|
+
} else {
|
|
136
|
+
log_debug(
|
|
137
|
+
"ClosedCaptioningManager: Vizio APIs are not available, skipping setup"
|
|
138
|
+
);
|
|
96
139
|
}
|
|
97
140
|
}
|
|
98
141
|
|
|
@@ -154,8 +154,8 @@ export class Player {
|
|
|
154
154
|
this.isSeeking()
|
|
155
155
|
? this.playerState.seekPosition
|
|
156
156
|
: this.playerState.adState
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
? this.playerState.adState.adPosition
|
|
158
|
+
: this.playerState.contentPosition;
|
|
159
159
|
|
|
160
160
|
getEntry = (): ZappEntry | null => this.entry;
|
|
161
161
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { TestScheduler } from "rxjs/testing";
|
|
2
|
+
|
|
3
|
+
import { withTimeout$ } from "..";
|
|
4
|
+
|
|
5
|
+
describe("withTimeout$", () => {
|
|
6
|
+
let testScheduler: TestScheduler;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
testScheduler = new TestScheduler((actual, expected) => {
|
|
10
|
+
expect(actual).toEqual(expected);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should emit undefined after the specified timeout", () => {
|
|
15
|
+
testScheduler.run(({ expectObservable }) => {
|
|
16
|
+
const timeout = 1000;
|
|
17
|
+
const expectedMarble = "1s (a|)";
|
|
18
|
+
const expectedValues = { a: undefined };
|
|
19
|
+
|
|
20
|
+
const result$ = withTimeout$(timeout);
|
|
21
|
+
|
|
22
|
+
expectObservable(result$).toBe(expectedMarble, expectedValues);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should complete after emitting undefined", () => {
|
|
27
|
+
testScheduler.run(({ expectObservable }) => {
|
|
28
|
+
const timeout = 500;
|
|
29
|
+
const expectedMarble = "500ms (a|)";
|
|
30
|
+
const expectedValues = { a: undefined };
|
|
31
|
+
|
|
32
|
+
const result$ = withTimeout$(timeout);
|
|
33
|
+
|
|
34
|
+
expectObservable(result$).toBe(expectedMarble, expectedValues);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
package/idleUtils/index.ts
CHANGED
package/idleUtils/withTimeout.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { of, Observable } from "rxjs";
|
|
2
|
+
import { delay } from "rxjs/operators";
|
|
3
|
+
|
|
4
|
+
export const withTimeout = (timeout: number): Promise<void> => {
|
|
5
|
+
return new Promise<void>((resolve) => {
|
|
3
6
|
setTimeout(() => {
|
|
4
7
|
resolve(undefined);
|
|
5
8
|
}, timeout);
|
|
6
9
|
});
|
|
7
10
|
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates an observable that emits a single value after a specified timeout.
|
|
14
|
+
*
|
|
15
|
+
* @param timeout - The delay duration in milliseconds before emitting the value.
|
|
16
|
+
* @returns An observable that emits `undefined` after the specified timeout.
|
|
17
|
+
*/
|
|
18
|
+
export const withTimeout$ = (timeout: number): Observable<void> => {
|
|
19
|
+
return of(undefined).pipe(delay(timeout));
|
|
20
|
+
};
|
package/logger/const.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/* eslint-disable unused-imports/no-unused-vars */
|
|
2
|
-
import * as R from "ramda";
|
|
3
|
-
|
|
4
1
|
enum XRayLogLevel {
|
|
5
2
|
verbose = 0,
|
|
6
3
|
debug = 1,
|
|
@@ -11,51 +8,9 @@ enum XRayLogLevel {
|
|
|
11
8
|
off = 100,
|
|
12
9
|
}
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
off = "off",
|
|
16
|
-
verbose = "verbose",
|
|
17
|
-
debug = "debug",
|
|
18
|
-
info = "info",
|
|
19
|
-
warning = "warning",
|
|
20
|
-
error = "error",
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const toastLevelToLogLevel = (toastLogLevel: ToastLogLevel): XRayLogLevel => {
|
|
24
|
-
if (R.isNil(toastLogLevel)) {
|
|
25
|
-
return XRayLogLevel.off;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
switch (toastLogLevel) {
|
|
29
|
-
case ToastLogLevel.verbose:
|
|
30
|
-
return XRayLogLevel.verbose;
|
|
31
|
-
case ToastLogLevel.debug:
|
|
32
|
-
return XRayLogLevel.debug;
|
|
33
|
-
case ToastLogLevel.info:
|
|
34
|
-
return XRayLogLevel.info;
|
|
35
|
-
case ToastLogLevel.error:
|
|
36
|
-
return XRayLogLevel.error;
|
|
37
|
-
default:
|
|
38
|
-
return XRayLogLevel.off;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const PLUGIN_IDENTIFIER = "xray_logging_plugin";
|
|
43
|
-
|
|
44
|
-
const wrapInObject = (obj, name) => {};
|
|
45
|
-
|
|
46
|
-
const applyConditions = (wrappedObj) => {};
|
|
47
|
-
|
|
48
|
-
const sanitizeEventPayload = () => {};
|
|
11
|
+
const wrapInObject = (_ctx: unknown, _key: string) => {};
|
|
49
12
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const isWeb = () => {};
|
|
53
|
-
|
|
54
|
-
const isDOMApp = () => {};
|
|
55
|
-
|
|
56
|
-
const isBrowser = () => {};
|
|
57
|
-
|
|
58
|
-
const eventAllowed = () => {};
|
|
13
|
+
const applyConditions = (_fn: unknown) => {};
|
|
59
14
|
|
|
60
15
|
/**
|
|
61
16
|
* This is the mocked version of XRayLogger
|
|
@@ -90,34 +45,21 @@ export default class XRayLogger {
|
|
|
90
45
|
);
|
|
91
46
|
};
|
|
92
47
|
|
|
93
|
-
log = (
|
|
94
|
-
const logEvent = typeof event === "string" ? { message: event } : event;
|
|
95
|
-
};
|
|
48
|
+
log = (_event) => {};
|
|
96
49
|
|
|
97
|
-
debug = (
|
|
98
|
-
const logEvent = typeof event === "string" ? { message: event } : event;
|
|
99
|
-
};
|
|
50
|
+
debug = (_event) => {};
|
|
100
51
|
|
|
101
|
-
info = (
|
|
102
|
-
const logEvent = typeof event === "string" ? { message: event } : event;
|
|
103
|
-
};
|
|
52
|
+
info = (_event) => {};
|
|
104
53
|
|
|
105
|
-
warning = (
|
|
106
|
-
const logEvent = typeof event === "string" ? { message: event } : event;
|
|
107
|
-
};
|
|
54
|
+
warning = (_event) => {};
|
|
108
55
|
|
|
109
|
-
warn = (
|
|
56
|
+
warn = (_event) => {
|
|
110
57
|
this.warning(event);
|
|
111
58
|
};
|
|
112
59
|
|
|
113
|
-
error = (
|
|
114
|
-
const logEvent: XRayEventData =
|
|
115
|
-
event instanceof Error
|
|
116
|
-
? { exception: event as Error, message: event.message }
|
|
117
|
-
: (event as XRayEventData);
|
|
118
|
-
};
|
|
60
|
+
error = (_event) => {};
|
|
119
61
|
|
|
120
|
-
sendEvent = (
|
|
62
|
+
sendEvent = (_event, _eventData) => {};
|
|
121
63
|
|
|
122
64
|
// To be used by QuickBrick Hook events
|
|
123
65
|
sendAudienceEvent = (event, eventData = null) => {
|
package/navigationUtils/index.ts
CHANGED
|
@@ -644,8 +644,8 @@ export const getScreenId = (
|
|
|
644
644
|
fallbackRiver: ZappRiver
|
|
645
645
|
) => {
|
|
646
646
|
return screenData?.targetScreen
|
|
647
|
-
? screenData?.targetScreen?.id ?? fallbackRiver.id
|
|
647
|
+
? (screenData?.targetScreen?.id ?? fallbackRiver.id)
|
|
648
648
|
: "screen_id" in screenData
|
|
649
|
-
|
|
650
|
-
|
|
649
|
+
? screenData.screen_id
|
|
650
|
+
: fallbackRiver.id;
|
|
651
651
|
};
|
package/numberUtils/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { logger } from "@applicaster/zapp-react-native-utils/logger";
|
|
|
3
3
|
|
|
4
4
|
const numberUtilsLogger = logger?.addSubsystem("NumberUtils");
|
|
5
5
|
|
|
6
|
-
export const toNumber = (value:
|
|
6
|
+
export const toNumber = (value: unknown): number | undefined => {
|
|
7
7
|
if (R.isNil(value) || R.isEmpty(value)) {
|
|
8
8
|
return undefined;
|
|
9
9
|
}
|
|
@@ -17,10 +17,12 @@ export const toNumber = (value: any): number | undefined => {
|
|
|
17
17
|
return undefined;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export const toNumberWithDefault = (
|
|
21
|
-
|
|
20
|
+
export const toNumberWithDefault = (
|
|
21
|
+
defaultValue: number,
|
|
22
|
+
value: unknown
|
|
23
|
+
): number => toNumber(value) ?? defaultValue;
|
|
22
24
|
|
|
23
|
-
export const toNumberWithDefaultZero = (value:
|
|
25
|
+
export const toNumberWithDefaultZero = (value: unknown): number =>
|
|
24
26
|
toNumberWithDefault(0, value);
|
|
25
27
|
|
|
26
28
|
export const requireNumber = (obj, key: string) => {
|
|
@@ -39,7 +41,7 @@ export const requireNumber = (obj, key: string) => {
|
|
|
39
41
|
|
|
40
42
|
export const toFiniteNumberWithDefault = (
|
|
41
43
|
defaultValue: number,
|
|
42
|
-
value:
|
|
44
|
+
value: unknown
|
|
43
45
|
): number => {
|
|
44
46
|
const possibleNumber = toNumberWithDefault(defaultValue, value);
|
|
45
47
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.4097222141",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "13.0.0-alpha.
|
|
31
|
+
"@applicaster/applicaster-types": "13.0.0-alpha.4097222141",
|
|
32
32
|
"buffer": "^5.2.1",
|
|
33
33
|
"camelize": "^1.0.0",
|
|
34
34
|
"create-react-context": "^0.2.3",
|
|
@@ -35,25 +35,23 @@ const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
|
35
35
|
const { useTrackedView } = require("../useTrackedView");
|
|
36
36
|
|
|
37
37
|
describe("useTrackCurrentAutoScrollingElement", () => {
|
|
38
|
-
it("should update position for selected component",
|
|
38
|
+
it("should update position for selected component - onViewportEnter", () => {
|
|
39
39
|
const { result } = renderHook(() => useTrackedView("123"), {
|
|
40
40
|
wrapper: Wrapper,
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
// Fast-forward until all timers have been executed
|
|
44
|
-
jest.advanceTimersByTime(3000);
|
|
45
|
-
|
|
46
43
|
expect(result.current.inViewPort).toBe(false);
|
|
47
44
|
|
|
48
45
|
const mockRect = {
|
|
49
46
|
rect: { left: 1, right: 1, top: 1, bottom: 1 },
|
|
50
47
|
};
|
|
51
48
|
|
|
52
|
-
act(() => {
|
|
53
|
-
result.current.onPositionUpdated(mockRect);
|
|
49
|
+
act(async () => {
|
|
50
|
+
await result.current.onPositionUpdated(mockRect);
|
|
54
51
|
});
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
// Fast-forward until all timers have been executed
|
|
54
|
+
jest.runAllTimers();
|
|
57
55
|
|
|
58
56
|
expect(result.current.inViewPort).toBe(true);
|
|
59
57
|
|
|
@@ -2,6 +2,10 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
2
2
|
import { useScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext";
|
|
3
3
|
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
|
|
4
4
|
import { findTrackedView } from "./utils/findTrackedView";
|
|
5
|
+
import { isNil } from "ramda";
|
|
6
|
+
import { withTimeout } from "@applicaster/zapp-react-native-utils/idleUtils";
|
|
7
|
+
|
|
8
|
+
const TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT = 500; // ms
|
|
5
9
|
|
|
6
10
|
const getNormalizedRect = (rect, componentId, screenWidth, screenHeight) => {
|
|
7
11
|
if (!rect) {
|
|
@@ -37,9 +41,16 @@ export const useTrackedView = (componentId: string) => {
|
|
|
37
41
|
);
|
|
38
42
|
|
|
39
43
|
const onPositionUpdated = useCallback(
|
|
40
|
-
({ rect }) => {
|
|
44
|
+
async ({ rect }) => {
|
|
41
45
|
const currentPosition = normalizedRect(componentId, rect);
|
|
42
46
|
|
|
47
|
+
// There is an issue on the native side where they are unable to guarantee
|
|
48
|
+
// that the order of onViewportLeave and onViewportEnter events is always correct.
|
|
49
|
+
// This workaround/hack delays the onViewportEnter event to ensure it is received last.
|
|
50
|
+
if (!isNil(currentPosition)) {
|
|
51
|
+
await withTimeout(TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT);
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
updateComponentsPositions(componentId, currentPosition as any);
|
|
44
55
|
|
|
45
56
|
setInViewPort(!!currentPosition);
|
|
@@ -25,6 +25,11 @@ jest.mock("@applicaster/zapp-react-native-utils/analyticsUtils/", () => ({
|
|
|
25
25
|
}),
|
|
26
26
|
}));
|
|
27
27
|
|
|
28
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
|
|
29
|
+
useTargetScreenData: jest.fn(() => ({})),
|
|
30
|
+
useCurrentScreenData: jest.fn(() => ({})),
|
|
31
|
+
}));
|
|
32
|
+
|
|
28
33
|
jest.mock("@applicaster/zapp-react-native-ui-components/Contexts", () => ({
|
|
29
34
|
...jest.requireActual(
|
|
30
35
|
"@applicaster/zapp-react-native-ui-components/Contexts"
|
|
@@ -16,6 +16,7 @@ import { ActionExecutorContext } from "@applicaster/zapp-react-native-utils/acti
|
|
|
16
16
|
import { isFunction, noop } from "../../functionUtils";
|
|
17
17
|
import { useSendAnalyticsOnPress } from "../analytics";
|
|
18
18
|
import { logOnPress, warnEmptyContentType } from "./helpers";
|
|
19
|
+
import { useCurrentScreenData } from "../screen";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* If onCellTap is defined execute the function and
|
|
@@ -44,6 +45,7 @@ export const useCellClick = ({
|
|
|
44
45
|
|
|
45
46
|
const onCellTap: Option<Function> = React.useContext(CellTapContext);
|
|
46
47
|
const actionExecutor = React.useContext(ActionExecutorContext);
|
|
48
|
+
const screenData = useCurrentScreenData();
|
|
47
49
|
|
|
48
50
|
const cellSelectable = toBooleanWithDefaultTrue(
|
|
49
51
|
component?.rules?.component_cells_selectable
|
|
@@ -78,7 +80,10 @@ export const useCellClick = ({
|
|
|
78
80
|
logOnPress(selectedItem, pathname, component, onCellTap);
|
|
79
81
|
|
|
80
82
|
if (selectedItem) {
|
|
81
|
-
await actionExecutor?.handleEntryActions(selectedItem
|
|
83
|
+
await actionExecutor?.handleEntryActions(selectedItem, {
|
|
84
|
+
component,
|
|
85
|
+
screenData,
|
|
86
|
+
});
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
if (selectedItem?.type?.value === "action") {
|
|
@@ -111,6 +116,7 @@ export const useCellClick = ({
|
|
|
111
116
|
pathname,
|
|
112
117
|
push,
|
|
113
118
|
sendAnalyticsOnPress,
|
|
119
|
+
screenData,
|
|
114
120
|
]
|
|
115
121
|
);
|
|
116
122
|
|
|
@@ -52,6 +52,14 @@ export const useDimensions: UseDimensions = (
|
|
|
52
52
|
? { fullDimensions }
|
|
53
53
|
: { ...fullDimensions };
|
|
54
54
|
|
|
55
|
+
if (options.updateForInactiveScreens === undefined) {
|
|
56
|
+
options.updateForInactiveScreens = true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options.fullDimensions === undefined) {
|
|
60
|
+
options.fullDimensions = false;
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
const [dimensions, setDimensions] = useState(getInitialDimensions(context));
|
|
56
64
|
const deviceInfo = useRef(getDeviceInfo(dimensions, appData));
|
|
57
65
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
2
|
-
|
|
3
1
|
import { platformSelect } from "../../reactUtils";
|
|
4
2
|
|
|
5
3
|
const TAB_BAR_HEIGHT_IOS = 49;
|
|
@@ -7,6 +5,6 @@ const TAB_BAR_HEIGHT_ANDROID = 56;
|
|
|
7
5
|
|
|
8
6
|
export const useGetTabBarHeight = () =>
|
|
9
7
|
platformSelect({
|
|
10
|
-
ios: TAB_BAR_HEIGHT_IOS
|
|
8
|
+
ios: TAB_BAR_HEIGHT_IOS,
|
|
11
9
|
android: TAB_BAR_HEIGHT_ANDROID,
|
|
12
10
|
}) as number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* returns a ref with an initial value that is lazily evaluated once
|
|
5
|
+
* */
|
|
6
|
+
export const useRefWithInitialValue = <T>(initialValueGetter: () => T) => {
|
|
7
|
+
const ref = React.useRef<T>(null);
|
|
8
|
+
|
|
9
|
+
if (ref.current === null) {
|
|
10
|
+
ref.current = initialValueGetter();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return ref;
|
|
14
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import type { Subject } from "rxjs";
|
|
3
|
+
|
|
4
|
+
export const useStateFromSubscribe = <T, U>(
|
|
5
|
+
subject: Subject<T>,
|
|
6
|
+
onUpdate: (
|
|
7
|
+
observerValue: T,
|
|
8
|
+
next: React.Dispatch<React.SetStateAction<U>>
|
|
9
|
+
) => void,
|
|
10
|
+
initialValue: U
|
|
11
|
+
) => {
|
|
12
|
+
const [state, setState] = useState<U>(initialValue);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const subscription = subject.subscribe((observer) =>
|
|
16
|
+
onUpdate(observer, setState)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return () => subscription.unsubscribe();
|
|
20
|
+
}, [subject]);
|
|
21
|
+
|
|
22
|
+
return state;
|
|
23
|
+
};
|
|
@@ -4,9 +4,10 @@ import { subscriber } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
4
4
|
const subscriberObjects = Object.create({});
|
|
5
5
|
|
|
6
6
|
interface UseSubscriberFor {
|
|
7
|
-
(
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
(
|
|
8
|
+
eventName: string,
|
|
9
|
+
handler?: (...args: unknown[]) => void
|
|
10
|
+
): (...args: unknown[]) => ReturnType<typeof subscriber>;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
/**
|
package/screenState/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { create } from "zustand";
|
|
2
2
|
import { produce } from "immer";
|
|
3
3
|
import { path } from "ramda";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { useShallow } from "zustand/react/shallow";
|
|
4
6
|
|
|
5
7
|
type ScreenState = {
|
|
6
8
|
selectedEntry: {
|
|
@@ -18,6 +20,8 @@ type ScreenStore = {
|
|
|
18
20
|
setSelectedEntry: (screenId: string, entryId: string) => void;
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
type SetSelectedEntry = (screenId: string, entryId: string) => void;
|
|
24
|
+
|
|
21
25
|
const useScreenStore = create<ScreenStore>((set) => ({
|
|
22
26
|
screens: screensInitialState,
|
|
23
27
|
setSelectedEntry: (screenId, entryId) =>
|
|
@@ -35,17 +39,27 @@ const useScreenStore = create<ScreenStore>((set) => ({
|
|
|
35
39
|
export function useScreenState(
|
|
36
40
|
screenId: ScreenId
|
|
37
41
|
): null | { screen: ScreenState; setSelectedEntry: (entryId: string) => void } {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
) as ScreenState;
|
|
42
|
+
const screenState = useScreenStore<ScreenState>(
|
|
43
|
+
useShallow(path(["screens", screenId]))
|
|
44
|
+
);
|
|
42
45
|
|
|
43
|
-
const setSelectedEntry = useScreenStore(
|
|
46
|
+
const setSelectedEntry = useScreenStore<SetSelectedEntry>(
|
|
47
|
+
useShallow(path(["setSelectedEntry"]))
|
|
48
|
+
);
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
const memoizedSetSelectedEntry = React.useCallback(
|
|
51
|
+
(entryId) => setSelectedEntry(screenId, entryId),
|
|
52
|
+
[screenId, setSelectedEntry]
|
|
53
|
+
);
|
|
46
54
|
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
return React.useMemo(
|
|
56
|
+
() =>
|
|
57
|
+
!screenId
|
|
58
|
+
? null
|
|
59
|
+
: {
|
|
60
|
+
screen: screenState,
|
|
61
|
+
setSelectedEntry: memoizedSetSelectedEntry,
|
|
62
|
+
},
|
|
63
|
+
[screenId, screenState]
|
|
64
|
+
);
|
|
51
65
|
}
|
package/theme/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export const ThemeContext = React.createContext({
|
|
|
14
14
|
export function useTheme<
|
|
15
15
|
T extends Record<string, any> =
|
|
16
16
|
| BaseThemePropertiesTV
|
|
17
|
-
| BaseThemePropertiesMobile
|
|
17
|
+
| BaseThemePropertiesMobile,
|
|
18
18
|
>(): T {
|
|
19
19
|
const { themes, selectedThemeId } = React.useContext(ThemeContext);
|
|
20
20
|
|