@applicaster/zapp-react-native-utils 12.0.0-alpha.4955589444 → 12.0.0-alpha.5000126055
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/analyticsUtils/AnalyticPlayerListener.ts +155 -0
- package/analyticsUtils/AnalyticsEvents/index.ts +6 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/index.tsx +6 -0
- package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
- package/appUtils/playerManager/DelayedSeekPlayerWrapper.tsx +180 -0
- package/appUtils/playerManager/index.ts +9 -27
- package/appUtils/playerManager/player.ts +14 -5
- package/appUtils/playerManager/playerNative.ts +9 -3
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +23 -4
- package/cellUtils/__tests__/cellUtils.test.ts +9 -20
- package/cellUtils/index.ts +6 -12
- package/dateUtils/index.ts +11 -0
- package/headersUtils/index.ts +1 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
- package/localizationUtils/index.ts +13 -22
- package/numberUtils/index.ts +4 -0
- package/package.json +2 -2
- package/reactHooks/cell-click/__tests__/index.test.js +5 -0
- package/reactHooks/cell-click/index.ts +2 -2
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/navigation/__mocks__/index.ts +13 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +21 -65
- package/reactHooks/player/__tests__/useAutoSeek.test.tsx +8 -1
- package/reactHooks/player/useAutoSeek.tsx +28 -8
- package/reactHooks/player/useSeek.tsx +4 -2
- package/reactHooks/player/useTapSeek.tsx +34 -7
- package/reactHooks/screen/useScreenContext.ts +4 -3
- package/screenState/index.ts +0 -8
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +24 -22
- package/types.ts +4 -0
|
@@ -91,6 +91,8 @@ export class Player {
|
|
|
91
91
|
this.onVideoProgress = this.onVideoProgress.bind(this);
|
|
92
92
|
this.onVideoLoad = this.onVideoLoad.bind(this);
|
|
93
93
|
this.isFullScreenSupported = this.isFullScreenSupported.bind(this);
|
|
94
|
+
this.onPlayerSeekComplete = this.onPlayerSeekComplete.bind(this);
|
|
95
|
+
|
|
94
96
|
this.entryObservable = null;
|
|
95
97
|
}
|
|
96
98
|
|
|
@@ -321,7 +323,7 @@ export class Player {
|
|
|
321
323
|
* You should use dispatchPlayerEvent at PlayerContainer or call playerManager.invokeHandler directly
|
|
322
324
|
* This allows you to use one method for everything.
|
|
323
325
|
*/
|
|
324
|
-
|
|
326
|
+
onPlayerSeekStart = (event: QuickBrickPlayer.OnSeekStartEvent) => {
|
|
325
327
|
const { isLive, seekableDuration, currentTime, duration, seekTime } = event;
|
|
326
328
|
|
|
327
329
|
this.setPlaybackState({ currentTime, duration, seekableDuration, isLive });
|
|
@@ -336,10 +338,11 @@ export class Player {
|
|
|
336
338
|
});
|
|
337
339
|
};
|
|
338
340
|
|
|
339
|
-
|
|
341
|
+
onPlayerSeekComplete(event: QuickBrickPlayer.OnSeekCompleteEvent) {
|
|
340
342
|
const { isLive, seekableDuration, currentTime, duration } = event;
|
|
341
343
|
|
|
342
344
|
this.setPlaybackState({ currentTime, duration, seekableDuration, isLive });
|
|
345
|
+
|
|
343
346
|
this.playerState.seekPosition = null;
|
|
344
347
|
|
|
345
348
|
if (!isLive) {
|
|
@@ -350,7 +353,7 @@ export class Player {
|
|
|
350
353
|
callbackName: SharedPlayerCallBacksKeys.OnPlayerSeekComplete,
|
|
351
354
|
event,
|
|
352
355
|
});
|
|
353
|
-
}
|
|
356
|
+
}
|
|
354
357
|
|
|
355
358
|
onVideoEnd = (event) => {
|
|
356
359
|
this.invokeListenersUpdate({
|
|
@@ -646,8 +649,8 @@ export class Player {
|
|
|
646
649
|
};
|
|
647
650
|
|
|
648
651
|
public getListener = (): QuickBrickPlayer.SharedPlayerCallBacks => ({
|
|
649
|
-
onPlayerSeekStart: this.
|
|
650
|
-
onPlayerSeekComplete: this.
|
|
652
|
+
onPlayerSeekStart: this.onPlayerSeekStart,
|
|
653
|
+
onPlayerSeekComplete: this.onPlayerSeekComplete,
|
|
651
654
|
onVideoEnd: this.onVideoEnd,
|
|
652
655
|
onError: this.onError,
|
|
653
656
|
onLoad: this.onLoad,
|
|
@@ -727,4 +730,10 @@ export class Player {
|
|
|
727
730
|
}
|
|
728
731
|
|
|
729
732
|
public supportsNativeControls = (): boolean => false;
|
|
733
|
+
public supportNativeCast = (): boolean => false;
|
|
734
|
+
|
|
735
|
+
public isInDelayedSeek = (): boolean => false;
|
|
736
|
+
public enterDelayedSeek() {}
|
|
737
|
+
|
|
738
|
+
public exitDelayedSeek() {}
|
|
730
739
|
}
|
|
@@ -70,7 +70,7 @@ export class PlayerNative extends Player {
|
|
|
70
70
|
currentPlayerComponent = (): ReactComponent<PlayerProps> =>
|
|
71
71
|
this.playerComponent?.current;
|
|
72
72
|
|
|
73
|
-
getState = () => this.
|
|
73
|
+
getState = () => this.playerState;
|
|
74
74
|
|
|
75
75
|
// TODO: Try to add module interface
|
|
76
76
|
invokeNativeFunction = (funcName: string, ...params: any[]): boolean => {
|
|
@@ -111,7 +111,7 @@ export class PlayerNative extends Player {
|
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
const newPosition = R.clamp(0,
|
|
114
|
+
const newPosition = R.clamp(0, this.playerState.seekableDuration, position);
|
|
115
115
|
|
|
116
116
|
if (
|
|
117
117
|
!this.invokeNativeFunction(
|
|
@@ -231,9 +231,10 @@ export class PlayerNative extends Player {
|
|
|
231
231
|
|
|
232
232
|
onVideoLoad = (event) => {
|
|
233
233
|
if (this.startPosition) {
|
|
234
|
-
super.onVideoLoad({ ...event, ignoreContinueWatching: true });
|
|
235
234
|
this.seekTo(this.startPosition);
|
|
236
235
|
this.startPosition = null;
|
|
236
|
+
|
|
237
|
+
super.onVideoLoad({ ...event, ignoreContinueWatching: true });
|
|
237
238
|
} else {
|
|
238
239
|
super.onVideoLoad(event);
|
|
239
240
|
}
|
|
@@ -295,4 +296,9 @@ export class PlayerNative extends Player {
|
|
|
295
296
|
|
|
296
297
|
supportsNativeControls = (): boolean =>
|
|
297
298
|
toBooleanWithDefaultFalse(this.getConfig()?.["supports_native_controls"]);
|
|
299
|
+
|
|
300
|
+
supportNativeCast = (): boolean =>
|
|
301
|
+
toBooleanWithDefaultFalse(
|
|
302
|
+
this.playerPluginId === "quick-brick-player-brightcove"
|
|
303
|
+
);
|
|
298
304
|
}
|
|
@@ -4,6 +4,9 @@ import { useEffect } from "react";
|
|
|
4
4
|
import { playerManager } from "./index";
|
|
5
5
|
import { useValidatePlayerConfig } from "../../playerUtils/useValidatePlayerConfig";
|
|
6
6
|
import { PlayerRole } from "./conts";
|
|
7
|
+
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
8
|
+
import { isTV } from "../../reactUtils";
|
|
9
|
+
import { DelayedSeekPlayerWrapper } from "./DelayedSeekPlayerWrapper";
|
|
7
10
|
|
|
8
11
|
// TODO: Rename to ControllerType
|
|
9
12
|
export const usePlayerControllerSetup = ({
|
|
@@ -34,17 +37,33 @@ export const usePlayerControllerSetup = ({
|
|
|
34
37
|
useValidatePlayerConfig(config);
|
|
35
38
|
|
|
36
39
|
useEffect(() => {
|
|
37
|
-
const
|
|
40
|
+
const newConfig = isAppleTV()
|
|
41
|
+
? { supports_native_controls: true, ...config }
|
|
42
|
+
: config;
|
|
43
|
+
|
|
44
|
+
const combinedProps = {
|
|
38
45
|
player: ref,
|
|
39
46
|
listener: props as any,
|
|
40
|
-
config,
|
|
47
|
+
config: newConfig,
|
|
41
48
|
playerId,
|
|
42
49
|
entry,
|
|
43
50
|
playerPluginId: pluginId,
|
|
44
51
|
playerRole: PlayerRole.Primary,
|
|
45
|
-
}
|
|
52
|
+
};
|
|
46
53
|
|
|
47
|
-
|
|
54
|
+
if (isTV()) {
|
|
55
|
+
const wrappedPlayerController = new ControllerType({
|
|
56
|
+
...combinedProps,
|
|
57
|
+
playerRole: PlayerRole.Unspecified,
|
|
58
|
+
playerId: playerId + "." + "wrapped",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
setPlayerController(
|
|
62
|
+
new DelayedSeekPlayerWrapper(combinedProps, wrappedPlayerController)
|
|
63
|
+
);
|
|
64
|
+
} else {
|
|
65
|
+
setPlayerController(new ControllerType(combinedProps));
|
|
66
|
+
}
|
|
48
67
|
}, [playerId, entry?.id]);
|
|
49
68
|
|
|
50
69
|
React.useEffect(() => {
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
EMPTY,
|
|
25
25
|
FALLBACK,
|
|
26
26
|
TRANSFORM,
|
|
27
|
-
defaultColor,
|
|
28
27
|
} from "./fixtures";
|
|
29
28
|
|
|
30
29
|
describe("getKeyForLabel", () => {
|
|
@@ -395,9 +394,7 @@ describe("getColorFromData", () => {
|
|
|
395
394
|
it("should return value directly if valid color", () => {
|
|
396
395
|
const result = getColorFromData({
|
|
397
396
|
data: entry,
|
|
398
|
-
|
|
399
|
-
getValue: getValue(componentStyle),
|
|
400
|
-
defaultColor,
|
|
397
|
+
valueFromLayout: "#123456",
|
|
401
398
|
});
|
|
402
399
|
|
|
403
400
|
expect(result).toBe("#123456");
|
|
@@ -406,9 +403,7 @@ describe("getColorFromData", () => {
|
|
|
406
403
|
it("should return valid rgba color name", () => {
|
|
407
404
|
const result = getColorFromData({
|
|
408
405
|
data: entry,
|
|
409
|
-
|
|
410
|
-
getValue: getValue(componentStyle),
|
|
411
|
-
defaultColor,
|
|
406
|
+
valueFromLayout: "rgba(255, 255, 255, 0)",
|
|
412
407
|
});
|
|
413
408
|
|
|
414
409
|
expect(result).toBe("rgba(255, 255, 255, 0)");
|
|
@@ -417,33 +412,27 @@ describe("getColorFromData", () => {
|
|
|
417
412
|
it("should return path value if path value is set and is valid color", () => {
|
|
418
413
|
const result = getColorFromData({
|
|
419
414
|
data: entry,
|
|
420
|
-
|
|
421
|
-
getValue: getValue(componentStyle),
|
|
422
|
-
defaultColor,
|
|
415
|
+
valueFromLayout: "background_color",
|
|
423
416
|
});
|
|
424
417
|
|
|
425
418
|
expect(result).toBe("#123456");
|
|
426
419
|
});
|
|
427
420
|
|
|
428
|
-
it("should return
|
|
421
|
+
it("should return path value if path value is set, nested and is valid color", () => {
|
|
429
422
|
const result = getColorFromData({
|
|
430
423
|
data: entry,
|
|
431
|
-
|
|
432
|
-
getValue: getValue(componentStyle),
|
|
433
|
-
defaultColor,
|
|
424
|
+
valueFromLayout: "extensions.background_color",
|
|
434
425
|
});
|
|
435
426
|
|
|
436
|
-
expect(result).toBe(
|
|
427
|
+
expect(result).toBe("#123456");
|
|
437
428
|
});
|
|
438
429
|
|
|
439
|
-
it("should return
|
|
430
|
+
it("should return valueFromLayout if path does not exist", () => {
|
|
440
431
|
const result = getColorFromData({
|
|
441
432
|
data: entry,
|
|
442
|
-
|
|
443
|
-
getValue: getValue(componentStyle),
|
|
444
|
-
defaultColor,
|
|
433
|
+
valueFromLayout: "invalid_color",
|
|
445
434
|
});
|
|
446
435
|
|
|
447
|
-
expect(result).toBe(
|
|
436
|
+
expect(result).toBe("invalid_color");
|
|
448
437
|
});
|
|
449
438
|
});
|
package/cellUtils/index.ts
CHANGED
|
@@ -447,30 +447,24 @@ export const toResizeMode = (
|
|
|
447
447
|
|
|
448
448
|
type GetColorFromData = {
|
|
449
449
|
data: Record<string, any>;
|
|
450
|
-
|
|
451
|
-
getValue: Function;
|
|
452
|
-
defaultColor: string;
|
|
450
|
+
valueFromLayout: string;
|
|
453
451
|
};
|
|
454
452
|
|
|
455
453
|
export const getColorFromData = ({
|
|
456
454
|
data,
|
|
457
|
-
|
|
458
|
-
getValue,
|
|
459
|
-
defaultColor,
|
|
455
|
+
valueFromLayout,
|
|
460
456
|
}: GetColorFromData): string => {
|
|
461
|
-
const value = getValue(key);
|
|
462
|
-
|
|
463
457
|
// Temporary hack to fix color validation when alpha is floating point number
|
|
464
458
|
// https://github.com/dreamyguy/validate-color/issues/44
|
|
465
|
-
if (validateColor(
|
|
466
|
-
return
|
|
459
|
+
if (validateColor(valueFromLayout.replace(".00", ""))) {
|
|
460
|
+
return valueFromLayout;
|
|
467
461
|
}
|
|
468
462
|
|
|
469
|
-
const pathValue = R.path(
|
|
463
|
+
const pathValue = R.path(valueFromLayout.split("."), data);
|
|
470
464
|
|
|
471
465
|
if (pathValue && validateColor(pathValue)) {
|
|
472
466
|
return pathValue;
|
|
473
467
|
}
|
|
474
468
|
|
|
475
|
-
return
|
|
469
|
+
return valueFromLayout;
|
|
476
470
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import utc from "dayjs/plugin/utc";
|
|
3
|
+
import timezone from "dayjs/plugin/timezone";
|
|
4
|
+
import isoWeek from "dayjs/plugin/isoWeek";
|
|
5
|
+
|
|
6
|
+
// Extend dayjs with plugins
|
|
7
|
+
dayjs.extend(utc);
|
|
8
|
+
dayjs.extend(timezone);
|
|
9
|
+
dayjs.extend(isoWeek);
|
|
10
|
+
|
|
11
|
+
export { dayjs };
|
package/headersUtils/index.ts
CHANGED
|
@@ -28,5 +28,6 @@ export const getAppDataHeaders = (screenId: string) => {
|
|
|
28
28
|
"x-applicaster-signed-device-info-token": appData.signedDeviceInfoToken,
|
|
29
29
|
"x-applicaster-device-make": appData.deviceMake,
|
|
30
30
|
"x-applicaster-device-model": appData.deviceModel,
|
|
31
|
+
"x-applicaster-uuid": appData?.uuid,
|
|
31
32
|
};
|
|
32
33
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { last, head, isNil, includes,
|
|
1
|
+
import { last, head, isNil, includes, pathOr } from "ramda";
|
|
2
2
|
|
|
3
3
|
const stripBrackets = (path) => {
|
|
4
4
|
const withoutPrepened = last(path.split("{{"));
|
|
@@ -13,15 +13,15 @@ const hasValue = (context) => (path) => {
|
|
|
13
13
|
return !isNil(value);
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const getMissingValues = (context, string): string[] => {
|
|
17
17
|
if (!includes("{{", string)) {
|
|
18
|
-
return
|
|
18
|
+
return [];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const SEARCH_REGEX = new RegExp(/{{.*?}}/g);
|
|
22
22
|
const paths = string.toString().match(SEARCH_REGEX);
|
|
23
23
|
|
|
24
|
-
return
|
|
24
|
+
return paths.filter((path) => !hasValue(context)(path));
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export const isNonInflatedUrl = (url: string): boolean =>
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const mocked_state = {
|
|
4
|
-
remoteConfigurations: { localizations: {} },
|
|
5
|
-
appData: {
|
|
6
|
-
languageCode: "en",
|
|
7
|
-
countryCode: "US",
|
|
8
|
-
},
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
let mocked_locale = ["en-US"];
|
|
12
|
-
|
|
13
|
-
jest.doMock("react-redux", () => ({
|
|
14
|
-
useSelector: jest.fn((fn) => fn(mocked_state)),
|
|
15
|
-
}));
|
|
1
|
+
import { NativeModules } from "react-native";
|
|
16
2
|
|
|
17
|
-
const
|
|
3
|
+
const settingsManagerMock = {
|
|
18
4
|
getConstants: jest.fn(() => ({
|
|
19
|
-
settings: { AppleLanguages:
|
|
5
|
+
settings: { AppleLanguages: ["en-US"] },
|
|
20
6
|
})),
|
|
21
7
|
};
|
|
22
8
|
|
|
23
|
-
const
|
|
9
|
+
const qbCommunicationModuleMock = {
|
|
24
10
|
languageLocale: "en",
|
|
25
11
|
countryLocale: "US",
|
|
12
|
+
uiLanguage: "en-US",
|
|
26
13
|
};
|
|
27
14
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ReactNative.NativeModules.QuickBrickCommunicationModule =
|
|
31
|
-
QuickBrickCommunicationModule;
|
|
32
|
-
|
|
33
|
-
const { useIsRTL } = require("../index");
|
|
15
|
+
NativeModules.SettingsManager = settingsManagerMock;
|
|
16
|
+
NativeModules.QuickBrickCommunicationModule = qbCommunicationModuleMock;
|
|
34
17
|
|
|
35
18
|
describe("localizationUtils", () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.resetModules();
|
|
21
|
+
});
|
|
22
|
+
|
|
36
23
|
describe("when the app has a single locale", () => {
|
|
37
24
|
describe("when the app has only a RTL language as locale", () => {
|
|
38
25
|
beforeEach(() => {
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
jest.resetModules();
|
|
27
|
+
const RN = require("react-native");
|
|
28
|
+
|
|
29
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
30
|
+
languageLocale: "he",
|
|
31
|
+
countryLocale: "IL",
|
|
32
|
+
uiLanguage: "he-HE",
|
|
41
33
|
};
|
|
42
34
|
});
|
|
43
35
|
|
|
44
36
|
it("useIsRTL returns true", () => {
|
|
37
|
+
const { useIsRTL } = require("../index");
|
|
45
38
|
expect(useIsRTL()).toBe(true);
|
|
46
39
|
});
|
|
47
40
|
});
|
|
48
41
|
|
|
49
42
|
describe("when the app has only a LTR language as locale", () => {
|
|
50
43
|
beforeEach(() => {
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
jest.resetModules();
|
|
45
|
+
|
|
46
|
+
const RN = require("react-native");
|
|
47
|
+
|
|
48
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
49
|
+
languageLocale: "en",
|
|
50
|
+
countryLocale: "US",
|
|
51
|
+
uiLanguage: "en",
|
|
53
52
|
};
|
|
54
53
|
});
|
|
55
54
|
|
|
56
55
|
it("useIsRTL returns false", () => {
|
|
56
|
+
const { useIsRTL } = require("../index");
|
|
57
57
|
expect(useIsRTL()).toBe(false);
|
|
58
58
|
});
|
|
59
59
|
});
|
|
@@ -63,45 +63,56 @@ describe("localizationUtils", () => {
|
|
|
63
63
|
describe("when device locale is in the app's locales", () => {
|
|
64
64
|
describe("when device locale is LTR", () => {
|
|
65
65
|
beforeEach(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
66
|
+
jest.resetModules();
|
|
67
|
+
|
|
68
|
+
const RN = require("react-native");
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
71
|
+
languageLocale: "en",
|
|
72
|
+
countryLocale: "US",
|
|
73
|
+
uiLanguage: "en-US",
|
|
74
|
+
};
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
it("useIsRTL returns false", () => {
|
|
78
|
+
const { useIsRTL } = require("../index");
|
|
75
79
|
expect(useIsRTL()).toBe(false);
|
|
76
80
|
});
|
|
77
81
|
});
|
|
78
82
|
|
|
79
83
|
describe("when device locale is RTL", () => {
|
|
80
84
|
beforeEach(() => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
en: "http://url.com",
|
|
84
|
-
};
|
|
85
|
+
jest.resetModules();
|
|
86
|
+
const RN = require("react-native");
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
89
|
+
languageLocale: "he",
|
|
90
|
+
countryLocale: "IL",
|
|
91
|
+
uiLanguage: "he",
|
|
92
|
+
};
|
|
87
93
|
});
|
|
88
94
|
|
|
89
95
|
it("useIsRTL returns true", () => {
|
|
96
|
+
const { useIsRTL } = require("../index");
|
|
90
97
|
expect(useIsRTL()).toBe(true);
|
|
91
98
|
});
|
|
92
99
|
});
|
|
93
100
|
|
|
94
101
|
describe("when a device has a secondary language in a supported language", () => {
|
|
95
102
|
beforeEach(() => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
};
|
|
103
|
+
jest.resetModules();
|
|
104
|
+
|
|
105
|
+
const RN = require("react-native");
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
108
|
+
languageLocale: "he",
|
|
109
|
+
countryLocale: "IL",
|
|
110
|
+
uiLanguage: "he",
|
|
111
|
+
};
|
|
102
112
|
});
|
|
103
113
|
|
|
104
114
|
it("useIsRTL returns true", () => {
|
|
115
|
+
const { useIsRTL } = require("../index");
|
|
105
116
|
expect(useIsRTL()).toBe(true);
|
|
106
117
|
});
|
|
107
118
|
});
|
|
@@ -110,30 +121,38 @@ describe("localizationUtils", () => {
|
|
|
110
121
|
describe("when device locale is not in the app's locales", () => {
|
|
111
122
|
describe("when first app locale is LTR", () => {
|
|
112
123
|
beforeEach(() => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
124
|
+
jest.resetModules();
|
|
125
|
+
|
|
126
|
+
const RN = require("react-native");
|
|
117
127
|
|
|
118
|
-
|
|
128
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
129
|
+
languageLocale: "fr",
|
|
130
|
+
countryLocale: "FR",
|
|
131
|
+
uiLanguage: "fr-FR",
|
|
132
|
+
};
|
|
119
133
|
});
|
|
120
134
|
|
|
121
135
|
it("useIsRTL returns false", () => {
|
|
136
|
+
const { useIsRTL } = require("../index");
|
|
122
137
|
expect(useIsRTL()).toBe(false);
|
|
123
138
|
});
|
|
124
139
|
});
|
|
125
140
|
|
|
126
141
|
describe("when first app locale is RTL", () => {
|
|
127
142
|
beforeEach(() => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
};
|
|
143
|
+
jest.resetModules();
|
|
144
|
+
|
|
145
|
+
const RN = require("react-native");
|
|
132
146
|
|
|
133
|
-
|
|
147
|
+
RN.NativeModules.QuickBrickCommunicationModule = {
|
|
148
|
+
languageLocale: "he",
|
|
149
|
+
countryLocale: "HE",
|
|
150
|
+
uiLanguage: "he",
|
|
151
|
+
};
|
|
134
152
|
});
|
|
135
153
|
|
|
136
154
|
it("useIsRTL returns true", () => {
|
|
155
|
+
const { useIsRTL } = require("../index");
|
|
137
156
|
expect(useIsRTL()).toBe(true);
|
|
138
157
|
});
|
|
139
158
|
});
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import { ViewStyle } from "react-native";
|
|
3
|
-
import { useSelector } from "react-redux";
|
|
4
3
|
|
|
5
|
-
import { getDeviceLocales } from "./deviceLocales";
|
|
6
4
|
import { useMemo } from "react";
|
|
7
5
|
import { getUILanguage } from "../appUtils/localizationsHelper";
|
|
6
|
+
import { utilsLogger } from "../logger";
|
|
8
7
|
|
|
9
8
|
export {
|
|
10
9
|
getLocale,
|
|
@@ -45,34 +44,26 @@ export function useLocalizedStrings({ localizations }) {
|
|
|
45
44
|
return result;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
function
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
)
|
|
47
|
+
export function getIsRTL(): boolean {
|
|
48
|
+
const uiLanguage = getUILanguage();
|
|
49
|
+
|
|
50
|
+
if (!uiLanguage) {
|
|
51
|
+
utilsLogger.error({ message: "getUILanguage returned null or undefined" });
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
return R.head(matchingLanguages);
|
|
53
|
+
return false;
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
}
|
|
56
|
+
const [languageCode] = uiLanguage.split("-");
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
const deviceLocales = getDeviceLocales() || [];
|
|
62
|
-
const localeToUse = getLocaleToUse(deviceLocales, R.keys(localizations));
|
|
58
|
+
const lowerCaseLanguageCode = languageCode.toLocaleLowerCase();
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
}
|
|
60
|
+
const isRTL = R.contains(lowerCaseLanguageCode, RTL_LOCALES);
|
|
66
61
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"localizations",
|
|
70
|
-
]);
|
|
62
|
+
return isRTL;
|
|
63
|
+
}
|
|
71
64
|
|
|
72
65
|
export function useIsRTL(): boolean {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return getIsRTLFromLocalizations(localizations);
|
|
66
|
+
return getIsRTL();
|
|
76
67
|
}
|
|
77
68
|
|
|
78
69
|
export const applyRTLStylesIfNeeded = (
|
package/numberUtils/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.5000126055",
|
|
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": "12.0.0-alpha.
|
|
31
|
+
"@applicaster/applicaster-types": "12.0.0-alpha.5000126055",
|
|
32
32
|
"buffer": "^5.2.1",
|
|
33
33
|
"camelize": "^1.0.0",
|
|
34
34
|
"create-react-context": "^0.2.3",
|
|
@@ -6,6 +6,7 @@ import { waitFor } from "@testing-library/react-native";
|
|
|
6
6
|
const navigator = {
|
|
7
7
|
getPathname: () => "pathnameMock",
|
|
8
8
|
push: jest.fn(),
|
|
9
|
+
data: {},
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
@@ -28,6 +29,10 @@ jest.mock("@applicaster/zapp-react-native-ui-components/Contexts", () => ({
|
|
|
28
29
|
},
|
|
29
30
|
}));
|
|
30
31
|
|
|
32
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
|
|
33
|
+
useScreenContext: jest.fn(() => navigator.data),
|
|
34
|
+
}));
|
|
35
|
+
|
|
31
36
|
const { useCellClick } = require("../");
|
|
32
37
|
|
|
33
38
|
const mockProps = {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { useContext } from "react";
|
|
4
5
|
import * as R from "ramda";
|
|
5
6
|
import { handleActionSchemeUrl } from "@applicaster/quick-brick-core/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/useUrlSchemeHandler";
|
|
6
7
|
import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
|
|
@@ -12,7 +13,6 @@ import {
|
|
|
12
13
|
import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
13
14
|
import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
14
15
|
import { noop } from "../../functionUtils";
|
|
15
|
-
import { useContext } from "react";
|
|
16
16
|
import { ActionExecutorContext } from "../../actionsExecutor/ActionExecutorContext";
|
|
17
17
|
import { useSendAnalyticsOnPress } from "../analytics";
|
|
18
18
|
import { logOnPress, warnEmptyContentType } from "./helpers";
|
|
@@ -83,7 +83,7 @@ export const useCellClick = (props: Props) => {
|
|
|
83
83
|
if (typeof onCellTap === "function") {
|
|
84
84
|
onCellTap(selectedItem, _index);
|
|
85
85
|
} else {
|
|
86
|
-
if (currentRoute === pathname || pathname
|
|
86
|
+
if (currentRoute === pathname || pathname.includes("video-modal")) {
|
|
87
87
|
const targetScreen = component?.data?.target;
|
|
88
88
|
|
|
89
89
|
push(
|