@applicaster/zapp-react-native-utils 14.0.0-alpha.7900711229 → 14.0.0-alpha.8220111512
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/ActionExecutorContext.tsx +83 -60
- package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
- package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
- package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
- package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
- package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
- package/analyticsUtils/events.ts +8 -0
- package/analyticsUtils/index.tsx +3 -4
- package/analyticsUtils/manager.ts +1 -1
- package/appUtils/HooksManager/Hook.ts +4 -4
- package/appUtils/HooksManager/index.ts +11 -1
- package/appUtils/accessibilityManager/index.ts +5 -5
- package/appUtils/contextKeysManager/contextResolver.ts +1 -14
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +1 -1
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
- package/appUtils/playerManager/useChapterMarker.tsx +0 -1
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
- package/arrayUtils/index.ts +1 -1
- package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
- package/componentsUtils/index.ts +4 -1
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
- package/configurationUtils/manifestKeyParser.ts +57 -32
- package/focusManager/FocusManager.ts +26 -16
- package/focusManager/Tree.ts +25 -21
- package/focusManager/__tests__/FocusManager.test.ts +50 -8
- package/index.d.ts +0 -9
- package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
- package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
- package/navigationUtils/index.ts +6 -4
- package/package.json +2 -3
- package/playerUtils/getPlayerActionButtons.ts +1 -1
- package/playerUtils/index.ts +51 -0
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +15 -14
- package/reactHooks/cell-click/index.ts +1 -8
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +0 -20
- package/reactHooks/feed/useBatchLoading.ts +9 -7
- package/reactHooks/feed/useFeedLoader.tsx +14 -17
- package/reactHooks/feed/usePipesCacheReset.ts +3 -3
- package/reactHooks/flatList/useSequentialRenderItem.tsx +3 -3
- package/reactHooks/layout/__tests__/index.test.tsx +3 -1
- package/reactHooks/layout/isTablet/index.ts +12 -5
- package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
- package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
- package/reactHooks/layout/useLayoutVersion.ts +5 -5
- package/reactHooks/navigation/index.ts +7 -5
- package/reactHooks/navigation/useIsScreenActive.ts +9 -5
- package/reactHooks/navigation/useRoute.ts +2 -7
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
- package/reactHooks/screen/useScreenContext.ts +1 -1
- package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
- package/reactHooks/state/useRivers.ts +7 -8
- package/riverComponetsMeasurementProvider/index.tsx +1 -1
- package/services/js2native.ts +1 -0
- package/testUtils/index.tsx +7 -8
- package/time/BackgroundTimer.ts +6 -4
- package/utils/index.ts +5 -0
- package/actionsExecutor/ScreenActions.ts +0 -163
- package/actionsExecutor/StorageActions.ts +0 -110
- package/actionsExecutor/feedDecorator.ts +0 -171
- package/actionsExecutor/screenResolver.ts +0 -11
- package/reactHooks/navigation/useScreenStateStore.ts +0 -11
- package/storage/ScreenSingleValueProvider.ts +0 -197
- package/storage/ScreenStateMultiSelectProvider.ts +0 -282
- package/storage/StorageMultiSelectProvider.ts +0 -192
- package/storage/StorageSingleSelectProvider.ts +0 -108
|
@@ -11,8 +11,11 @@ const currentPlatform = platformSelect({
|
|
|
11
11
|
android_tv: "android",
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// Do not change the order, focused_selected should be first
|
|
15
|
+
const states = ["focused_selected", "pressed", "focused", "selected"];
|
|
16
|
+
|
|
15
17
|
const platformSuffixes = ["ios", "tvos", "samsung", "lg", "android"];
|
|
18
|
+
type StateKey = (typeof states)[number] | "default";
|
|
16
19
|
|
|
17
20
|
export type GetAllSpecificStylesProps = {
|
|
18
21
|
componentName: string;
|
|
@@ -33,39 +36,47 @@ export const getAllSpecificStyles = ({
|
|
|
33
36
|
subComponentName,
|
|
34
37
|
outStyles,
|
|
35
38
|
}: GetAllSpecificStylesProps) => {
|
|
36
|
-
if (!outStyles)
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
+
if (!outStyles) throw new Error("outStyles is required");
|
|
40
|
+
if (!componentName) throw new Error("componentName is required");
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
const prefix =
|
|
43
|
+
subComponentName?.length > 0
|
|
44
|
+
? `${componentName}_style_${subComponentName}_`
|
|
45
|
+
: `${componentName}_style_`;
|
|
42
46
|
|
|
43
47
|
const defaultKey = "default";
|
|
44
48
|
|
|
45
|
-
if (!outStyles[defaultKey]) {
|
|
46
|
-
|
|
47
|
-
}
|
|
49
|
+
if (!outStyles[defaultKey]) outStyles[defaultKey] = {};
|
|
50
|
+
|
|
51
|
+
const tmpGenericDict: Record<StateKey, Record<string, any>> = {};
|
|
52
|
+
const tmpPlatformDict: Record<StateKey, Record<string, any>> = {};
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
const parseKey = (key: string, value: any) => {
|
|
50
55
|
if (!key.startsWith(prefix)) {
|
|
51
56
|
return;
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
let styleName = key.slice(prefix.length);
|
|
60
|
+
if (!styleName || styleName.startsWith("_")) return;
|
|
55
61
|
|
|
56
|
-
const platform = platformSuffixes.find((
|
|
57
|
-
styleName.startsWith(
|
|
62
|
+
const platform = platformSuffixes.find((prefix) =>
|
|
63
|
+
styleName.startsWith(prefix)
|
|
58
64
|
);
|
|
59
65
|
|
|
66
|
+
let tmpDict = tmpGenericDict;
|
|
67
|
+
|
|
60
68
|
if (platform) {
|
|
61
69
|
if (currentPlatform !== platform) {
|
|
62
|
-
return;
|
|
70
|
+
return;
|
|
63
71
|
}
|
|
64
72
|
|
|
73
|
+
tmpDict = tmpPlatformDict;
|
|
65
74
|
styleName = styleName.slice(platform.length + 1);
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
let state =
|
|
77
|
+
let state = states.find((prefix) => styleName.startsWith(prefix)) as
|
|
78
|
+
| StateKey
|
|
79
|
+
| undefined;
|
|
69
80
|
|
|
70
81
|
if (state) {
|
|
71
82
|
styleName = styleName.slice(state.length + 1);
|
|
@@ -73,30 +84,44 @@ export const getAllSpecificStyles = ({
|
|
|
73
84
|
state = defaultKey;
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
|
|
87
|
+
if (!styleName) return;
|
|
77
88
|
|
|
78
|
-
|
|
89
|
+
const camelCaseKey = toCamelCase(styleName);
|
|
79
90
|
|
|
80
|
-
if (!
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
91
|
+
if (!tmpDict[state]) tmpDict[state] = {};
|
|
92
|
+
tmpDict[state][camelCaseKey] = value;
|
|
93
|
+
};
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
95
|
+
for (const [key, value] of Object.entries(configuration)) {
|
|
96
|
+
parseKey(key, value);
|
|
97
|
+
}
|
|
88
98
|
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
const allStates = Array.from(
|
|
100
|
+
new Set<StateKey>([
|
|
101
|
+
defaultKey,
|
|
102
|
+
...(Object.keys(tmpGenericDict) as StateKey[]),
|
|
103
|
+
...(Object.keys(tmpPlatformDict) as StateKey[]),
|
|
104
|
+
...(Object.keys(outStyles) as StateKey[]),
|
|
105
|
+
])
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
for (const state of allStates) {
|
|
109
|
+
outStyles[state] = Object.assign(
|
|
110
|
+
{},
|
|
111
|
+
outStyles[state] || {},
|
|
112
|
+
tmpGenericDict[state] || {},
|
|
113
|
+
tmpPlatformDict[state] || {}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
91
116
|
|
|
92
117
|
// Merge default styles with state specific styles
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (key === defaultKey) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
118
|
+
for (const state of Object.keys(outStyles)) {
|
|
119
|
+
if (state === defaultKey) continue;
|
|
98
120
|
|
|
99
|
-
|
|
100
|
-
|
|
121
|
+
outStyles[state] = Object.assign(
|
|
122
|
+
{},
|
|
123
|
+
outStyles[defaultKey],
|
|
124
|
+
outStyles[state]
|
|
125
|
+
);
|
|
101
126
|
}
|
|
102
127
|
};
|
|
@@ -176,18 +176,30 @@ class FocusManager {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
registerFocusable(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
isFocusableCell
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
registerFocusable({
|
|
180
|
+
touchableRef,
|
|
181
|
+
parentFocusableRef,
|
|
182
|
+
isFocusableCell,
|
|
183
|
+
parentFocusableId,
|
|
184
|
+
}: {
|
|
185
|
+
touchableRef: FocusManager.TouchableReactRef;
|
|
186
|
+
parentFocusableRef: FocusManager.TouchableReactRef;
|
|
187
|
+
isFocusableCell: boolean;
|
|
188
|
+
parentFocusableId: string;
|
|
189
|
+
}) {
|
|
190
|
+
const focusableId = getFocusableId(touchableRef);
|
|
191
|
+
|
|
185
192
|
const focusableComponent = FocusManager.findFocusable(focusableId);
|
|
186
193
|
|
|
187
|
-
if (!focusableComponent &&
|
|
188
|
-
this.focusableComponents.push(
|
|
194
|
+
if (!focusableComponent && touchableRef) {
|
|
195
|
+
this.focusableComponents.push(touchableRef);
|
|
189
196
|
|
|
190
|
-
this.tree.add(
|
|
197
|
+
this.tree.add(
|
|
198
|
+
touchableRef,
|
|
199
|
+
parentFocusableRef,
|
|
200
|
+
isFocusableCell,
|
|
201
|
+
parentFocusableId
|
|
202
|
+
);
|
|
191
203
|
} else {
|
|
192
204
|
logger.warning("Focusable component already registered", {
|
|
193
205
|
id: focusableId,
|
|
@@ -243,12 +255,10 @@ class FocusManager {
|
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
blurPrevious(options?: FocusManager.Android.CallbackOptions) {
|
|
246
|
-
|
|
247
|
-
FocusManager.instance.prevFocused
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
);
|
|
251
|
-
}
|
|
258
|
+
FocusManager.instance.prevFocused?.onBlur?.(
|
|
259
|
+
FocusManager.instance.prevFocused,
|
|
260
|
+
options ?? {} // Adding fallback to avoid potential regression caused by #7509
|
|
261
|
+
);
|
|
252
262
|
}
|
|
253
263
|
|
|
254
264
|
onDisableFocusChange = (id) => {
|
|
@@ -269,7 +279,7 @@ class FocusManager {
|
|
|
269
279
|
|
|
270
280
|
if (nextFocus) {
|
|
271
281
|
// HACK: hack to fix the hack below
|
|
272
|
-
// HACK: putting call to the end of the event loop so the next component has a
|
|
282
|
+
// HACK: putting call to the end of the event loop so the next component has a chance to be registered
|
|
273
283
|
setTimeout(() => {
|
|
274
284
|
FocusManager.instance.setFocus(nextFocus, {
|
|
275
285
|
direction: "down",
|
package/focusManager/Tree.ts
CHANGED
|
@@ -8,37 +8,41 @@ export class Tree {
|
|
|
8
8
|
this.tree = focusManagerTree;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
add(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
add(
|
|
12
|
+
touchableRef: FocusManager.TouchableReactRef,
|
|
13
|
+
parentFocusableRef: FocusManager.TouchableReactRef,
|
|
14
|
+
isFocusableCell: boolean,
|
|
15
|
+
parentFocusableId: string
|
|
16
|
+
) {
|
|
17
|
+
const focusableId = getFocusableId(touchableRef);
|
|
18
|
+
const parentId = getFocusableId(parentFocusableRef) || parentFocusableId;
|
|
14
19
|
const focusableComponentInTree = this.find(focusableId);
|
|
15
20
|
|
|
16
21
|
// update node if it already exists
|
|
17
22
|
if (focusableComponentInTree) {
|
|
18
|
-
focusableComponentInTree.updateNode(
|
|
23
|
+
focusableComponentInTree.updateNode(touchableRef);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
if (!this.find(parentId)) {
|
|
27
|
+
// create temporary node to the root of the tree
|
|
28
|
+
this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
|
|
29
|
+
}
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
const parentNode = this.find(parentId);
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
if (parentNode) {
|
|
34
|
+
if (focusableComponentInTree) {
|
|
35
|
+
focusableComponentInTree.isFocusableCell = isFocusableCell;
|
|
36
|
+
focusableComponentInTree.parentId = parentNode.id;
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
parentNode.addChild(focusableComponentInTree);
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
40
|
+
// remove root object from the list
|
|
41
|
+
this.tree = this.tree.filter(
|
|
42
|
+
(node) => node !== focusableComponentInTree
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
parentNode.addChild(touchableRef, focusableId, isFocusableCell);
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { focusManager } from "../FocusManager";
|
|
2
2
|
|
|
3
|
+
const isFocusableCell = true;
|
|
4
|
+
const parentFocusableId = "parentFocusableId";
|
|
5
|
+
|
|
3
6
|
const group = {
|
|
4
7
|
current: {
|
|
5
8
|
props: {
|
|
@@ -62,13 +65,47 @@ jest.useFakeTimers();
|
|
|
62
65
|
|
|
63
66
|
describe("FocusManager", () => {
|
|
64
67
|
beforeAll(() => {
|
|
65
|
-
focusManager.registerFocusable(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
focusManager.registerFocusable({
|
|
69
|
+
touchableRef: group,
|
|
70
|
+
parentFocusableRef: { current: null },
|
|
71
|
+
isFocusableCell,
|
|
72
|
+
parentFocusableId,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
focusManager.registerFocusable({
|
|
76
|
+
touchableRef: child1,
|
|
77
|
+
parentFocusableRef: group,
|
|
78
|
+
isFocusableCell,
|
|
79
|
+
parentFocusableId,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
focusManager.registerFocusable({
|
|
83
|
+
touchableRef: child2,
|
|
84
|
+
parentFocusableRef: group,
|
|
85
|
+
isFocusableCell,
|
|
86
|
+
parentFocusableId,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
focusManager.registerFocusable({
|
|
90
|
+
touchableRef: child3,
|
|
91
|
+
parentFocusableRef: child2,
|
|
92
|
+
isFocusableCell,
|
|
93
|
+
parentFocusableId,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
focusManager.registerFocusable({
|
|
97
|
+
touchableRef: child4,
|
|
98
|
+
parentFocusableRef: child2,
|
|
99
|
+
isFocusableCell,
|
|
100
|
+
parentFocusableId,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
focusManager.registerFocusable({
|
|
104
|
+
touchableRef: child5,
|
|
105
|
+
parentFocusableRef: child2,
|
|
106
|
+
isFocusableCell,
|
|
107
|
+
parentFocusableId,
|
|
108
|
+
});
|
|
72
109
|
});
|
|
73
110
|
|
|
74
111
|
it("focusManager should be defined", () => {
|
|
@@ -199,7 +236,12 @@ describe("FocusManager", () => {
|
|
|
199
236
|
});
|
|
200
237
|
|
|
201
238
|
it("focusManager registerFocusable should register", () => {
|
|
202
|
-
focusManager.registerFocusable(
|
|
239
|
+
focusManager.registerFocusable({
|
|
240
|
+
touchableRef: child5,
|
|
241
|
+
parentFocusableRef: child2,
|
|
242
|
+
isFocusableCell,
|
|
243
|
+
parentFocusableId,
|
|
244
|
+
});
|
|
203
245
|
|
|
204
246
|
expect(
|
|
205
247
|
focusManager.isFocusableChildOf(child5.current.props.id, child2)
|
package/index.d.ts
CHANGED
|
@@ -137,12 +137,3 @@ declare type AccessibilityState = {
|
|
|
137
137
|
reduceMotionEnabled: boolean;
|
|
138
138
|
boldTextEnabled: boolean;
|
|
139
139
|
};
|
|
140
|
-
|
|
141
|
-
declare type AccessibilityProps = {
|
|
142
|
-
accessibilityLabel?: string;
|
|
143
|
-
accessibilityHint?: string;
|
|
144
|
-
"aria-label"?: string;
|
|
145
|
-
"aria-description"?: string;
|
|
146
|
-
accessibilityRole?: string;
|
|
147
|
-
"aria-role"?: string;
|
|
148
|
-
};
|
|
@@ -2985,6 +2985,14 @@ function getPlayerConfiguration({ platform, version }) {
|
|
|
2985
2985
|
type: "uploader",
|
|
2986
2986
|
default: "",
|
|
2987
2987
|
},
|
|
2988
|
+
{
|
|
2989
|
+
key: "audio_player_background_image_overlay",
|
|
2990
|
+
label: "Background Image Overlay",
|
|
2991
|
+
label_tooltip:
|
|
2992
|
+
"Add a semi-transparent color overlay to improve text readability over the background image.",
|
|
2993
|
+
type: "color_picker_rgba",
|
|
2994
|
+
initial_value: "rgba(17, 17, 17, 0.5)",
|
|
2995
|
+
},
|
|
2988
2996
|
{
|
|
2989
2997
|
type: "text_input",
|
|
2990
2998
|
label: "Item Image Key",
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { mapContentTypesToRivers } from "../index";
|
|
2
|
+
|
|
3
|
+
describe("mapContentTypesToRivers", () => {
|
|
4
|
+
it("should return the correct content types mapped to rivers", () => {
|
|
5
|
+
const state = {
|
|
6
|
+
rivers: {
|
|
7
|
+
"river-1": {
|
|
8
|
+
plugin_type: "river",
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
contentTypes: {
|
|
12
|
+
"content-type-1": {
|
|
13
|
+
screen_id: "river-1",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const result = mapContentTypesToRivers(state);
|
|
19
|
+
|
|
20
|
+
expect(result).toEqual({
|
|
21
|
+
"content-type-1": {
|
|
22
|
+
screenType: "river",
|
|
23
|
+
screen_id: "river-1",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return null if contentTypes is undefined", () => {
|
|
29
|
+
const state = {
|
|
30
|
+
rivers: {
|
|
31
|
+
"river-1": {
|
|
32
|
+
plugin_type: "river",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
// contentTypes is missing
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const result = mapContentTypesToRivers(state);
|
|
39
|
+
|
|
40
|
+
expect(result).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should skip content types whose screen does not exist in rivers", () => {
|
|
44
|
+
const state = {
|
|
45
|
+
rivers: {
|
|
46
|
+
"river-1": {
|
|
47
|
+
plugin_type: "river",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
contentTypes: {
|
|
51
|
+
"content-type-1": {
|
|
52
|
+
screen_id: "river-1",
|
|
53
|
+
},
|
|
54
|
+
"content-type-2": {
|
|
55
|
+
screen_id: "river-2", // river-2 does not exist
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const result = mapContentTypesToRivers(state);
|
|
61
|
+
|
|
62
|
+
expect(result).toEqual({
|
|
63
|
+
"content-type-1": {
|
|
64
|
+
screenType: "river",
|
|
65
|
+
screen_id: "river-1",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// result is not null, but may be undefined for missing keys
|
|
70
|
+
expect(result && result["content-type-2"]).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should use 'type' if 'plugin_type' is not present in river", () => {
|
|
74
|
+
const state = {
|
|
75
|
+
rivers: {
|
|
76
|
+
"river-1": {
|
|
77
|
+
type: "custom-type",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
contentTypes: {
|
|
81
|
+
"content-type-1": {
|
|
82
|
+
screen_id: "river-1",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const result = mapContentTypesToRivers(state);
|
|
88
|
+
|
|
89
|
+
expect(result).toEqual({
|
|
90
|
+
"content-type-1": {
|
|
91
|
+
screenType: "custom-type",
|
|
92
|
+
screen_id: "river-1",
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should skip content types if neither plugin_type nor type is present in river", () => {
|
|
98
|
+
const state = {
|
|
99
|
+
rivers: {
|
|
100
|
+
"river-1": {
|
|
101
|
+
// no plugin_type or type
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
contentTypes: {
|
|
105
|
+
"content-type-1": {
|
|
106
|
+
screen_id: "river-1",
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const result = mapContentTypesToRivers(state);
|
|
112
|
+
|
|
113
|
+
expect(result).toEqual({});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("should handle empty contentTypes object", () => {
|
|
117
|
+
const state = {
|
|
118
|
+
rivers: {
|
|
119
|
+
"river-1": {
|
|
120
|
+
plugin_type: "river",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
contentTypes: {},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const result = mapContentTypesToRivers(state);
|
|
127
|
+
|
|
128
|
+
expect(result).toEqual({});
|
|
129
|
+
});
|
|
130
|
+
});
|
package/navigationUtils/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isPlayable,
|
|
14
14
|
isV2River,
|
|
15
15
|
} from "./itemTypeMatchers";
|
|
16
|
+
import { RootState } from "@applicaster/zapp-react-native-redux/store";
|
|
16
17
|
|
|
17
18
|
type PathAttribute = {
|
|
18
19
|
screenType: string;
|
|
@@ -377,10 +378,11 @@ export const usesVideoModal = (
|
|
|
377
378
|
return targetScreenConfiguration?.styles?.use_video_modal;
|
|
378
379
|
};
|
|
379
380
|
|
|
380
|
-
export const mapContentTypesToRivers = (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
381
|
+
export const mapContentTypesToRivers = (
|
|
382
|
+
state: Partial<RootState>
|
|
383
|
+
): ZappContentTypesMapped | null => {
|
|
384
|
+
const { rivers, contentTypes } = state;
|
|
385
|
+
|
|
384
386
|
if (!contentTypes) {
|
|
385
387
|
return null;
|
|
386
388
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.8220111512",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@applicaster/applicaster-types": "14.0.0-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "14.0.0-alpha.8220111512",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@applicaster/zapp-pipes-v2-client": "*",
|
|
40
40
|
"@react-native-community/netinfo": "*",
|
|
41
|
-
"immer": "*",
|
|
42
41
|
"react": "*",
|
|
43
42
|
"react-native": "*",
|
|
44
43
|
"uglify-js": "*",
|
package/playerUtils/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { isFilledArray } from "@applicaster/zapp-react-native-utils/arrayUtils";
|
|
|
5
5
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
6
|
|
|
7
7
|
import { getBoolFromConfigValue } from "../configurationUtils";
|
|
8
|
+
import { Dimensions } from "react-native";
|
|
8
9
|
|
|
9
10
|
export { getPlayerActionButtons } from "./getPlayerActionButtons";
|
|
10
11
|
|
|
@@ -97,3 +98,53 @@ export const isAudioItem = (item: Option<ZappEntry>) => {
|
|
|
97
98
|
export const isInlineTV = (screenData) => {
|
|
98
99
|
return isTV() && isFilledArray(screenData?.ui_components);
|
|
99
100
|
};
|
|
101
|
+
|
|
102
|
+
const isPercentage = (value: string | number): boolean => {
|
|
103
|
+
if (typeof value === "string") {
|
|
104
|
+
return value.includes("%");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getPercentageOf = (percent: string, value: number) => {
|
|
111
|
+
const percentageValue = parseFloat(percent.replace("%", ""));
|
|
112
|
+
|
|
113
|
+
if (isNaN(percentageValue)) {
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (value * percentageValue) / 100;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
type DimensionsT = {
|
|
121
|
+
width: number | string;
|
|
122
|
+
height: number | string | undefined;
|
|
123
|
+
aspectRatio?: number;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const getTabletWidth = (
|
|
127
|
+
tablet_landscape_sidebar_width,
|
|
128
|
+
dimensions: DimensionsT
|
|
129
|
+
) => {
|
|
130
|
+
const { width: SCREEN_WIDTH } = Dimensions.get("screen");
|
|
131
|
+
|
|
132
|
+
const { width } = dimensions;
|
|
133
|
+
let widthValue = Number(width);
|
|
134
|
+
|
|
135
|
+
if (isPercentage(width)) {
|
|
136
|
+
widthValue = getPercentageOf(width.toString(), SCREEN_WIDTH);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const sidebarWidth = Number(tablet_landscape_sidebar_width?.replace("%", ""));
|
|
140
|
+
|
|
141
|
+
if (tablet_landscape_sidebar_width?.includes("%")) {
|
|
142
|
+
return widthValue * (1 - sidebarWidth / 100);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (Number.isNaN(sidebarWidth)) {
|
|
146
|
+
return widthValue * 0.65;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return widthValue - sidebarWidth;
|
|
150
|
+
};
|