@applicaster/zapp-react-native-utils 15.0.0-alpha.5949018320 → 15.0.0-alpha.6010600030
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/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +3 -0
- package/appUtils/focusManager/index.ios.ts +35 -2
- package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
- package/appUtils/focusManagerAux/utils/utils.ios.ts +55 -1
- package/manifestUtils/defaultManifestConfigurations/player.js +5 -10
- package/package.json +4 -4
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +1 -1
- package/stringUtils/index.ts +1 -1
- package/testUtils/index.tsx +1 -1
- package/utils/__tests__/mergeRight.test.ts +48 -0
- package/utils/index.ts +2 -0
- package/utils/mergeRight.ts +5 -0
|
@@ -1,11 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import {
|
|
1
|
+
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
|
|
2
|
+
import { QUICK_BRICK_CONTENT } from "@applicaster/quick-brick-core/const";
|
|
3
|
+
import { isNil, isEmpty } from "@applicaster/zapp-react-native-utils/utils";
|
|
4
|
+
import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
4
5
|
|
|
5
6
|
let riverFocusData = {};
|
|
6
7
|
let initialyPresentedScreenFocused = false;
|
|
7
8
|
|
|
8
9
|
export const riverFocusManager = (function () {
|
|
10
|
+
/**
|
|
11
|
+
* Create unique key that will be used for save focused group data inside specific screen
|
|
12
|
+
* @param {{ screenId: string, isInsideContainer: boolean }}
|
|
13
|
+
* screenId Unique Id of the screen from layout.json
|
|
14
|
+
* isInsideContainer If this screen a screen picker child
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
function screenFocusableGroupId({
|
|
18
|
+
screenId,
|
|
19
|
+
isInsideContainer,
|
|
20
|
+
}: {
|
|
21
|
+
screenId: string;
|
|
22
|
+
isInsideContainer: Option<boolean>;
|
|
23
|
+
}) {
|
|
24
|
+
return `${QUICK_BRICK_CONTENT}-${screenId}${
|
|
25
|
+
isNil(isInsideContainer) ? "" : "-isInsideContainer"
|
|
26
|
+
}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
9
29
|
function setScreenFocusableData({
|
|
10
30
|
screenFocusableGroupId,
|
|
11
31
|
groupId,
|
|
@@ -78,8 +98,8 @@ export const riverFocusManager = (function () {
|
|
|
78
98
|
}) {
|
|
79
99
|
// Check if screen should be focused
|
|
80
100
|
const shouldFocus =
|
|
81
|
-
(initialyPresentedScreenFocused === false &&
|
|
82
|
-
|
|
101
|
+
(initialyPresentedScreenFocused === false && isEmpty(riverFocusData)) ||
|
|
102
|
+
isNotNil(riverFocusData[screenFocusableGroupId]) ||
|
|
83
103
|
isDeepLink;
|
|
84
104
|
|
|
85
105
|
// TODO: Uncommit it to start fixing bug where selection wrong item
|
|
@@ -118,19 +138,6 @@ export const riverFocusManager = (function () {
|
|
|
118
138
|
}
|
|
119
139
|
}
|
|
120
140
|
|
|
121
|
-
/**
|
|
122
|
-
* Create unique key that will be used for save focused group data inside specific screen
|
|
123
|
-
* @param {{ screenId: string, isInsideContainer: boolean }}
|
|
124
|
-
* screenId Unique Id of the screen from layout.json
|
|
125
|
-
* isInsideContainer If this screen a screen picker child
|
|
126
|
-
*
|
|
127
|
-
*/
|
|
128
|
-
function screenFocusableGroupId({ screenId, isInsideContainer }) {
|
|
129
|
-
return `RiverFocusableGroup-${screenId}${
|
|
130
|
-
R.isNil(isInsideContainer) ? "" : "-isInsideContainer"
|
|
131
|
-
}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
141
|
return {
|
|
135
142
|
setScreenFocusableData,
|
|
136
143
|
clearAllScreensData,
|
|
@@ -71,6 +71,9 @@ exports[`focusManagerIOS should be defined 1`] = `
|
|
|
71
71
|
"invokeHandler": [Function],
|
|
72
72
|
"isChildOf": [Function],
|
|
73
73
|
"isFocusOn": [Function],
|
|
74
|
+
"isFocusOnContent": [Function],
|
|
75
|
+
"isFocusOnMenu": [Function],
|
|
76
|
+
"isFocusOnTabsScreenContent": [Function],
|
|
74
77
|
"isGroupItemFocused": [Function],
|
|
75
78
|
"moveFocus": [Function],
|
|
76
79
|
"on": [Function],
|
|
@@ -4,7 +4,11 @@ import * as R from "ramda";
|
|
|
4
4
|
import {
|
|
5
5
|
isCurrentFocusOn,
|
|
6
6
|
isChildOf as isChildOfUtils,
|
|
7
|
-
|
|
7
|
+
isPartOfMenu,
|
|
8
|
+
isPartOfContent,
|
|
9
|
+
isPartOfTabsScreenContent,
|
|
10
|
+
} from "../focusManagerAux/utils/index.ios";
|
|
11
|
+
|
|
8
12
|
import { Tree } from "./treeDataStructure/Tree";
|
|
9
13
|
import { findFocusableNode } from "./treeDataStructure/Utils";
|
|
10
14
|
import { subscriber } from "../../functionUtils";
|
|
@@ -279,7 +283,9 @@ export const focusManager = (function () {
|
|
|
279
283
|
function setFocus(
|
|
280
284
|
id: string,
|
|
281
285
|
direction?: FocusManager.IOS.Direction,
|
|
282
|
-
options?: Partial<{
|
|
286
|
+
options?: Partial<{
|
|
287
|
+
groupFocusedChanged: boolean;
|
|
288
|
+
}>,
|
|
283
289
|
callback?: any
|
|
284
290
|
) {
|
|
285
291
|
blur(direction);
|
|
@@ -418,6 +424,30 @@ export const focusManager = (function () {
|
|
|
418
424
|
return id && isCurrentFocusOn(id, currentFocusNode);
|
|
419
425
|
}
|
|
420
426
|
|
|
427
|
+
function isFocusOnMenu(): boolean {
|
|
428
|
+
const currentFocusable = getCurrentFocus();
|
|
429
|
+
|
|
430
|
+
return isPartOfMenu(focusableTree, currentFocusable?.props?.id);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function isFocusOnContent(): boolean {
|
|
434
|
+
const currentFocusable = getCurrentFocus();
|
|
435
|
+
|
|
436
|
+
return isPartOfContent(focusableTree, currentFocusable?.props?.id);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function isFocusOnTabsScreenContent(
|
|
440
|
+
screenPickerContentContainerId: string
|
|
441
|
+
): boolean {
|
|
442
|
+
const currentFocusable = getCurrentFocus();
|
|
443
|
+
|
|
444
|
+
return isPartOfTabsScreenContent(
|
|
445
|
+
focusableTree,
|
|
446
|
+
screenPickerContentContainerId,
|
|
447
|
+
currentFocusable?.props?.id
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
421
451
|
function isChildOf(childId, parentId): boolean {
|
|
422
452
|
return isChildOfUtils(focusableTree, childId, parentId);
|
|
423
453
|
}
|
|
@@ -444,6 +474,9 @@ export const focusManager = (function () {
|
|
|
444
474
|
isGroupItemFocused,
|
|
445
475
|
getPreferredFocusChild,
|
|
446
476
|
isFocusOn,
|
|
477
|
+
isFocusOnMenu,
|
|
478
|
+
isFocusOnContent,
|
|
479
|
+
isFocusOnTabsScreenContent,
|
|
447
480
|
isChildOf,
|
|
448
481
|
};
|
|
449
482
|
})();
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { isNil, startsWith } from "@applicaster/zapp-react-native-utils/utils";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
QUICK_BRICK_CONTENT,
|
|
5
|
+
QUICK_BRICK_NAVBAR,
|
|
6
|
+
} from "@applicaster/quick-brick-core/const";
|
|
7
|
+
|
|
8
|
+
const isNavBar = (node) => startsWith(QUICK_BRICK_NAVBAR, node?.id);
|
|
9
|
+
const isContent = (node) => startsWith(QUICK_BRICK_CONTENT, node?.id);
|
|
10
|
+
const isRoot = (node) => node?.id === "root";
|
|
11
|
+
|
|
12
|
+
export const isPartOfTabsScreenContent = (
|
|
13
|
+
focusableTree,
|
|
14
|
+
screenPickerContentContainerId,
|
|
15
|
+
id
|
|
16
|
+
) => {
|
|
17
|
+
const node = focusableTree.findInTree(id);
|
|
18
|
+
|
|
19
|
+
if (isNil(node)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (isRoot(node)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isNavBar(node)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isContent(node)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (node?.id === screenPickerContentContainerId) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return isPartOfTabsScreenContent(
|
|
40
|
+
focusableTree,
|
|
41
|
+
screenPickerContentContainerId,
|
|
42
|
+
node.parent?.id
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const isPartOfMenu = (focusableTree, id): boolean => {
|
|
47
|
+
const node = focusableTree.findInTree(id);
|
|
48
|
+
|
|
49
|
+
if (isNil(node)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (isRoot(node)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (isNavBar(node)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isContent(node)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return isPartOfMenu(focusableTree, node.parent?.id);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const isPartOfContent = (focusableTree, id) => {
|
|
69
|
+
const node = focusableTree.findInTree(id);
|
|
70
|
+
|
|
71
|
+
if (isNil(node)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (isRoot(node)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (isNavBar(node)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (isContent(node)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return isPartOfContent(focusableTree, node.parent?.id);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const isCurrentFocusOn = (id, node) => {
|
|
91
|
+
if (!node) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (isRoot(node)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (node?.id === id) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return isCurrentFocusOn(id, node.parent);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const isChildOf = (focusableTree, childId, parentId) => {
|
|
107
|
+
if (isNil(childId) || isNil(parentId)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const childNode = focusableTree.findInTree(childId);
|
|
112
|
+
|
|
113
|
+
if (isNil(childNode)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (childNode.parent?.id === parentId) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return isChildOf(focusableTree, childNode.parent?.id, parentId);
|
|
122
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ReplaySubject, Subject } from "rxjs";
|
|
2
|
-
import { filter, switchMap, take, map } from "rxjs/operators";
|
|
2
|
+
import { filter, switchMap, take, withLatestFrom, map } from "rxjs/operators";
|
|
3
|
+
|
|
3
4
|
import { BUTTON_PREFIX } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const";
|
|
4
5
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
|
|
6
|
+
import { isPartOfMenu, isPartOfContent } from "./index.ios";
|
|
5
7
|
|
|
6
8
|
type FocusableID = string;
|
|
7
9
|
type RegistrationEvent = {
|
|
@@ -175,3 +177,55 @@ export const emitNativeRegistered = ({
|
|
|
175
177
|
focusableNativeGroupRegistrationSubject$.next({ id, groupId });
|
|
176
178
|
}
|
|
177
179
|
};
|
|
180
|
+
|
|
181
|
+
// /////
|
|
182
|
+
|
|
183
|
+
const focusedSubject$ = new Subject<FocusableID>();
|
|
184
|
+
|
|
185
|
+
const focused$ = focusedSubject$.asObservable();
|
|
186
|
+
|
|
187
|
+
export const emitFocused = (id: FocusableID): void => {
|
|
188
|
+
focusedSubject$.next(id);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const topMenuItemFocused$ = focused$.pipe(
|
|
192
|
+
filter((id) => id && isPartOfMenu(focusManager.focusableTree, id))
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
export const contentFocused$ = focused$.pipe(
|
|
196
|
+
filter((id) => {
|
|
197
|
+
const isContent = isPartOfContent(focusManager.focusableTree, id);
|
|
198
|
+
|
|
199
|
+
return id && isContent;
|
|
200
|
+
})
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const createFocusableRegistry = () => {
|
|
204
|
+
const subject$ = new ReplaySubject<FocusableID | undefined>(1);
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
observable$: subject$.asObservable(),
|
|
208
|
+
register: (id: FocusableID) => {
|
|
209
|
+
// save focusable_id on registration
|
|
210
|
+
subject$.next(id);
|
|
211
|
+
},
|
|
212
|
+
unregister: () => {
|
|
213
|
+
// reset focusable_id on unregistration
|
|
214
|
+
subject$.next(undefined);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/// HOME_TOP_MENU_ITEM
|
|
220
|
+
export const HomeTopMenuItemRegistry = createFocusableRegistry();
|
|
221
|
+
|
|
222
|
+
export const homeTopMenuItemFocused$ = topMenuItemFocused$.pipe(
|
|
223
|
+
withLatestFrom(HomeTopMenuItemRegistry.observable$),
|
|
224
|
+
filter(([id, homeId]) => id === homeId)
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
/// SCREEN_PICKER
|
|
228
|
+
export const ScreenPickerContentContainerRegistry = createFocusableRegistry();
|
|
229
|
+
|
|
230
|
+
/// SEARCH_INPUT
|
|
231
|
+
export const SearchInputRegistry = createFocusableRegistry();
|
|
@@ -1216,40 +1216,35 @@ function getPlayerConfiguration({ platform, version }) {
|
|
|
1216
1216
|
label: "Playback Speed 0.8x",
|
|
1217
1217
|
type: "uploader",
|
|
1218
1218
|
label_tooltip: "Playback Speed 0.8x",
|
|
1219
|
-
initial_value:
|
|
1220
|
-
"data:image/png;base64,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",
|
|
1219
|
+
initial_value: null,
|
|
1221
1220
|
},
|
|
1222
1221
|
{
|
|
1223
1222
|
key: "speed_1",
|
|
1224
1223
|
label: "Playback Speed 1x",
|
|
1225
1224
|
type: "uploader",
|
|
1226
1225
|
label_tooltip: "Playback Speed 1x",
|
|
1227
|
-
initial_value:
|
|
1228
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAI4SURBVHgB7dzhcRJBGIDhT8cCkg6SDmIHsQNLiBUYKwAqUCtIC5ZACVqBdIAdxN3JMSLecXcE8Tt5npkdJlxyf97ZcLcLRAAAAAAAAAAAAAAAAAAAAAAAAADAMb2IiViv17fl4aGMq45fub68vFwFv3kVyZWwF+VhVsZ9MFrqwANmLT1SBm5mbQ37NniWl5FMifu+PHwPcY8izQwuYa/iadbeBkeTaQbfxf64P8r4GoyS7l90h89lXJfxLRgl+23Sqox35f52WX8o/8aDcTLP4EUZrzdxOUzGGbws40MJ6/X2CDIFrhdRNeyn4GjSBBb275jKVTQHEvg/d/aB69Lo+sljGR/jADvnmEUiZx242a2qr/0XzVP35bmHkeeY7Zxj3pw3hXOfwTctz90NjdzEnbccuo0kzj1w1712b+Q9cfed9+TOOnCzSrboONwZuSfuopz3SyRx9hdZJcY8RkQeELfr2D/hNimGR55a3Cr9m+5OpcZpdqvabnNq5HpBdtPx5ynjVmbwlp6ZPLm4lcA7eiLvSh23ErjFwMjp41YCd3t85vEUBG7Rc7W8Mc+27txG4B0D426kjyzwlp64y47nU0cWuDFgEeNNdF94pY0scAxfoeq5uk4Z2Yb/yOXHqUW24X/A2vKAyGk+OGfDv13vIsaBy5onZ8P/T4NXqPZEtuGfwdaG/yp+vfF+HiNsRV5tnSPNhv9kvoSlaj75f9F2zBewAAAAAAAAAAAAAAAAAAAAAAAAwHT8BNhH51wNSx95AAAAAElFTkSuQmCC",
|
|
1226
|
+
initial_value: null,
|
|
1229
1227
|
},
|
|
1230
1228
|
{
|
|
1231
1229
|
key: "speed_1_2",
|
|
1232
1230
|
label: "Playback Speed 1.2x",
|
|
1233
1231
|
type: "uploader",
|
|
1234
1232
|
label_tooltip: "Playback Speed 1.2x",
|
|
1235
|
-
initial_value:
|
|
1236
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAUjSURBVHgB7d3bUeNIFAbgA7Xv2EUCmgiWjWBNBAwRYCKYdQQrIliIYEUEw0awymDIYDQBUFC8g+eccWsulPomteTu1v9VdZlSGyP0W1KrWxciAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgPgc0Mw8Pj4u+KUt4mm5XDaUqVED5oX5gV/ea6o3vGDvaQI8Hyt+ueAir4XmbTIvNZebnAIfJWBeoCf88g/tFqjOKS/ImkbE8/FezUdBfu5o9wVsKHGHFJBs/rjIAv1E5nBHpebjX/7xI/mHK+SL8Zk/429K3G8UiNoMykItaI/UPvZ/Lic0XMmfR7wmX1GiBq/BP621slAL2j9Z60KE25KQ/6JEDdoHD9jHieD7YJ6fNe22IjpPXG5p16Bq1DT5MpyReZciv/eO5/eJEtN7E63C/Wh5myyQBU1Hu888ODi42263lx0h1Vyu1ZdDvqxd8yvTZC0uKTFDNtGm4GQhbrjc0ERUy73QVNeLxeLctAZyXcUv56R3QQkK2or+9oGHhxXtNmfXNK2Voe6SHKhdxq2muuAvUUGJCRlww+X06Ojock/7qj810+89j2fvDHUFJSZUwLIp/mPsjgsL3S7jC/mZpHdtKkOPg2VhbPYcbEuOVbs2rw35mbJROLohAdeqYRKFgF+ywlCX3GFS7010xiMwZ5rpzVSDIyEFb0WnTLWS1111fHRQU4IQ8K+0vWCvr69J9kcjYEWNHK001c5jxNIvz2XLpfdolIyEtZ/x/Pw8qIMFAdP3ExNKTXVDjl2UqruzHZgoaDdQ4RWyGuZct5/x8vJSqRGyXmYfMC88WUNMvW6nHh03q45pziG/Cdf2uU5mHbAKtzK8xfesjloz3RqyIVzRu/U+24Adwr3y7U+XfgFujOn6srUhW8K9GnJIOsuAHcMtqYfj4+O1T8gO4ZY0wOwCdgj3duhCdQ157HDFrAJ2DHdNATiELCcmrjX1QcIVswl4ynBblpB1540FC1fMImB1nFsZ3hI83JYl5LeChiuyD1jt70yt4dHCbTmGHDxckXXAKtzS8JbRw23xYMXW8hZbfb+/S5mKKVxLa7nl3a3pItiVDaGpoTs5NVf6YeW8qjuP300t3FbwKymiDLgrIJ4m3XXWfuGEwpX/p6slHTTk6AJWIzJlR5UsDDnR/tTwu7ZwGy6Vuo6qF9dTg1w6MR4eHireN3cNBwYLOcY1+MxQt5Khs661WF0/VJJZQbtrqPpquLyzvcm1h0pa1xwyjRlyjI0s29jnief0Sfl2P/r2XfuKMWDbeczRnvimdi9rTbX2ONch5N5f3hgDrgx1N8u4r/BbaaZbOzEsIRfUU3QBq0aMXEvUvKmS1m/s1+nWHdOce6gMIffeao3dyJJj10ZTp5v+beCcN0s17farsk9uHFqvFenPqAjFuPVQ813wjx/UJO+TBiRk/gz5Oxfq7w0a8AcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANif7B8Q/dOlJHI7iEJNvlcl+8tCsg5Y3R/Ldm1QuUz46aI2ud9lx+XCr1HubhOLLNdgh6eQdjn3uZNPKnIN+DP5XzQtl6ha77+Rmuw20eoOOgX5K4bcfSdWOe6Dh9yMJYobuYSUY8BDnj2Y1XMLRY4BD7lJS3LPJrTJMeAht1lK7tmENmhF/4BWdEI25C/L3qwsA1YdFj6BXcX0LOSQcu+LLvnF1g258b2XVUrmMppUcvmdfhznNlz+43Kd+2jSV0z9PFgMpokeAAAAAElFTkSuQmCC",
|
|
1233
|
+
initial_value: null,
|
|
1237
1234
|
},
|
|
1238
1235
|
{
|
|
1239
1236
|
key: "speed_1_5",
|
|
1240
1237
|
label: "Playback Speed 1.5x",
|
|
1241
1238
|
type: "uploader",
|
|
1242
1239
|
label_tooltip: "Playback Speed 1.5x",
|
|
1243
|
-
initial_value:
|
|
1244
|
-
"data:image/png;base64,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",
|
|
1240
|
+
initial_value: null,
|
|
1245
1241
|
},
|
|
1246
1242
|
{
|
|
1247
1243
|
key: "speed_2",
|
|
1248
1244
|
label: "Playback Speed 2x",
|
|
1249
1245
|
type: "uploader",
|
|
1250
1246
|
label_tooltip: "Playback Speed 2x",
|
|
1251
|
-
initial_value:
|
|
1252
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQnSURBVHgB7d2PUdRAFMfxh2MBUIGxArECjwqECjwqUCowV4FYgdABVCAdSAekg7ME35pFgnOb3ZDAvmy+n5lMGJLL3dzvkuyfZCMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2LMnM7Hdbvd11p2ag4ODRtDLdMAa6kpnH3U61qkKrHbrp0sN/EbwiMmAfbBfdVrJMI1OZxr0leAvcwFruC7YWsY515DPBLYC1nC/6eyLTONCQz6VhXslRvg9d6pwnbX/wSyaiT1Yg6h0dhdZzZ1Xr6U9zzqHOn2QtgDW52jJhS8rAf/Q2Tqw2JWQT0JVIv/j+CnhUvaNvvZIFip7wL5+uw0sbqTdA5vINiqd/ZK2fryLbuLgtyyQhXPwYc+yTUpjhl/ne88qK1koCwGvQgs0uAtJ17duJQtlIeDQYfVWBojs6fuyUK8lP1c63hXmlOfMRZ5/newBT1WF0YJW37m8kYUy09Axgb6ABx3uSzKb7sI+vqrlqknVjsXJ9WC/HRlTpZpiG1MqZQ92zZxVYNmlJPBNpdv2z6c1cfrXjdrG1Ga/B+sX+Vln54HFV7onnUh8GytpW8O6BnVWBFrjTnJ3Xc56D/YFq1C47hCZ2mW46/y99qGlfI5QU+uhZDbbgDtt0CFJrWBeqBAWDTnSjn4jmc0y4E64oQYMF+65JPJVtU1gcTDkSLgbC71YszsHJ/QeuWuz1vK0bdfSFth2eXROTgi3FgNmFXBCuLf6xb6Xce9RSyTkuYTrzOmyWVdg6Tssu/Po0RT1z0jIjYR/YKbCdWYR8EuG23nPWsIh72IuXMd8wDnC7bx3LWkhmwzXsX7he7ZwO5+hlv6QzYbrmK0mWQjXezNyeVZW72wwEW6ktNxl9hpsc3uwfqmfZF7hOsnNmi/NVMA+3AsJh9tI24CfM9ybwP9Nhmzpzob7cEMaSbiEdoLPEWvEcH3Lg5s1c7Fy4Xss3PueoUaeKKVdeEgL1ZBmzZwsXPi+kv5eoUnoF74X+Rx9N77trArNIWQLh+hKMtOgjmVguI7/f9/h+lgyK+miuzGqwP+jjRiRkOnwN2JXh39yC1VPyFeSGQHLvwKYu3bLBd1IOwxELQP49U//28atZGahkFXJC9wcNvA+JwAAAAAAAAAAAAAAAAAAAAAAAIxWxIjvffytMW5M6e4ziO+fOTxkRNpZKjrgyGDh92oNeSOFKvbuQj9Ef8qQwrVft0hF7sEa2FpnQwdDyT78/nMoNeA7GT40RKMBv5XCFHeI9oO6VDJc5V9blBLPwWPGxcg+psbUSgx4X55uzGtNKjHgMcMcPvfItS+uxIDHDHySfdCUqVGKfkApekZSn3jWVWRrVpEB+waLIYFtSh1mqfS26FriD9U4G/KUtLlZSm9SrdM7eajnNjpd63Reem/SH2FDq35f8ateAAAAAElFTkSuQmCC",
|
|
1247
|
+
initial_value: null,
|
|
1253
1248
|
},
|
|
1254
1249
|
{
|
|
1255
1250
|
key: "sleep_timer",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "15.0.0-alpha.
|
|
3
|
+
"version": "15.0.0-alpha.6010600030",
|
|
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-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "15.0.0-alpha.6010600030",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
34
|
+
"handlebars": "4.7.8",
|
|
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": "*",
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import { Provider } from "react-redux";
|
|
3
3
|
import { renderHook } from "@testing-library/react-hooks";
|
|
4
4
|
import configureStore from "redux-mock-store";
|
|
5
|
-
import thunk from "redux-thunk";
|
|
5
|
+
import { thunk } from "redux-thunk";
|
|
6
6
|
|
|
7
7
|
const mockStore = configureStore([thunk]);
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import { Provider } from "react-redux";
|
|
3
3
|
import { renderHook } from "@testing-library/react-hooks";
|
|
4
4
|
import configureStore from "redux-mock-store";
|
|
5
|
-
import thunk from "redux-thunk";
|
|
5
|
+
import { thunk } from "redux-thunk";
|
|
6
6
|
|
|
7
7
|
const mockStore = configureStore([thunk]);
|
|
8
8
|
|
package/stringUtils/index.ts
CHANGED
package/testUtils/index.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import React, { PropsWithChildren } from "react";
|
|
|
4
4
|
import configureStore from "redux-mock-store";
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
6
|
import { View } from "react-native";
|
|
7
|
-
import thunk from "redux-thunk";
|
|
7
|
+
import { thunk } from "redux-thunk";
|
|
8
8
|
import * as R from "ramda";
|
|
9
9
|
|
|
10
10
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { mergeRight } from "../mergeRight";
|
|
2
|
+
|
|
3
|
+
describe("mergeRight", () => {
|
|
4
|
+
test("merges two objects with no overlapping keys", () => {
|
|
5
|
+
const a = { x: 1, y: 2 };
|
|
6
|
+
const b = { z: 3 };
|
|
7
|
+
|
|
8
|
+
const result = mergeRight(a, b);
|
|
9
|
+
|
|
10
|
+
expect(result).toEqual({ x: 1, y: 2, z: 3 });
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("overwrites keys from the second object", () => {
|
|
14
|
+
const a = { x: 1, y: 2 };
|
|
15
|
+
const b = { y: 10, z: 3 };
|
|
16
|
+
|
|
17
|
+
const result = mergeRight(a, b);
|
|
18
|
+
|
|
19
|
+
expect(result).toEqual({ x: 1, y: 10, z: 3 });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("does not mutate the original objects", () => {
|
|
23
|
+
const a = { x: 1 };
|
|
24
|
+
const b = { y: 2 };
|
|
25
|
+
|
|
26
|
+
const result = mergeRight(a, b);
|
|
27
|
+
|
|
28
|
+
expect(result).not.toBe(a);
|
|
29
|
+
expect(result).not.toBe(b);
|
|
30
|
+
expect(a).toEqual({ x: 1 });
|
|
31
|
+
expect(b).toEqual({ y: 2 });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("works with empty objects", () => {
|
|
35
|
+
expect(mergeRight({}, { a: 1 })).toEqual({ a: 1 });
|
|
36
|
+
expect(mergeRight({ a: 1 }, {})).toEqual({ a: 1 });
|
|
37
|
+
expect(mergeRight({}, {})).toEqual({});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("works with nested objects (shallow merge only)", () => {
|
|
41
|
+
const a = { x: { nested: 1 }, y: 2 };
|
|
42
|
+
const b = { x: { nested: 10 }, z: 3 };
|
|
43
|
+
|
|
44
|
+
const result = mergeRight(a, b);
|
|
45
|
+
|
|
46
|
+
expect(result).toEqual({ x: { nested: 10 }, y: 2, z: 3 });
|
|
47
|
+
});
|
|
48
|
+
});
|
package/utils/index.ts
CHANGED