@applicaster/zapp-react-native-utils 13.0.0-alpha.7222542422 → 13.0.0-alpha.7846284820

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.
@@ -16,7 +16,7 @@ const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
16
16
  * @returns {number} index
17
17
  */
18
18
  const hookState: (
19
- arg0: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS]
19
+ arg0: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS]
20
20
  ) => number = R.indexOf(R.__, R.values(HOOKS_EVENTS));
21
21
 
22
22
  /**
@@ -62,7 +62,7 @@ export class Hook implements HookInterface {
62
62
  * @param {Array<Any>} args variadic arguments to invoke the handler with
63
63
  */
64
64
  setStateAndNotify(
65
- event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
65
+ event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
66
66
  ...args
67
67
  ) {
68
68
  this.state = hookState(event);
@@ -103,7 +103,7 @@ export interface Hook<T extends HookModule = HookModule> {
103
103
  identifier: string;
104
104
  configuration: T["configuration"];
105
105
  setStateAndNotify(
106
- event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
106
+ event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
107
107
  opts: {
108
108
  error?: typeof Error;
109
109
  route?: string;
@@ -112,7 +112,7 @@ export interface Hook<T extends HookModule = HookModule> {
112
112
  }
113
113
  );
114
114
  general?: {
115
- transition_type: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS];
115
+ transition_type: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS];
116
116
  allow_screen_plugin_presentation: boolean;
117
117
  is_flow_blocker: boolean;
118
118
  };
@@ -42,12 +42,16 @@ export const resolveObjectValues = async (
42
42
 
43
43
  const resolvedEntries = await Promise.all(
44
44
  entries.map(async ([key, value]) => {
45
- const regex = /@{([^/]+)\/([^}]*)}/;
46
-
47
45
  if (typeof value !== "string") {
48
46
  return [key, value];
49
47
  }
50
48
 
49
+ if (!value.startsWith("@")) {
50
+ return [key, value];
51
+ }
52
+
53
+ const regex = /@{([^/]+)\/([^}]*)}/;
54
+
51
55
  const match = (value as string).match(regex);
52
56
 
53
57
  if (match) {
@@ -13,6 +13,7 @@ import {
13
13
  import { subscriber } from "../../functionUtils";
14
14
  import { coreLogger } from "../../logger";
15
15
  import { ACTION } from "./utils/enums";
16
+
16
17
  const logger = coreLogger.addSubsystem("focusManager");
17
18
 
18
19
  const isFocusEnabled = (focusableItem): boolean => {
@@ -325,8 +326,6 @@ export const focusManager = (function () {
325
326
  },
326
327
  });
327
328
 
328
- currentFocusNode = focusCandidate;
329
-
330
329
  focusableItem && setFocus(focusCandidate.id, null);
331
330
 
332
331
  return { success: true };
@@ -477,7 +476,7 @@ export const focusManager = (function () {
477
476
  function isCurrentFocusOnTheTopScreen() {
478
477
  const routes = R.pathOr([], ["root", "children"], focusableTree);
479
478
 
480
- if (routes.length <= 1) {
479
+ if (currentFocusNode && routes.length <= 1) {
481
480
  // there is only one or zero routes
482
481
  return true;
483
482
  }
@@ -154,8 +154,8 @@ export class Player {
154
154
  this.isSeeking()
155
155
  ? this.playerState.seekPosition
156
156
  : this.playerState.adState
157
- ? this.playerState.adState.adPosition
158
- : this.playerState.contentPosition;
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
+ });
@@ -1,4 +1,4 @@
1
- export { withTimeout } from "./withTimeout";
1
+ export { withTimeout, withTimeout$ } from "./withTimeout";
2
2
 
3
3
  export { onIdle } from "./onIdle";
4
4
 
@@ -1,7 +1,20 @@
1
- export const withTimeout = (timeout: number) => {
2
- return new Promise((resolve) => {
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
+ };
@@ -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
- ? screenData.screen_id
650
- : fallbackRiver.id;
649
+ ? screenData.screen_id
650
+ : fallbackRiver.id;
651
651
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "13.0.0-alpha.7222542422",
3
+ "version": "13.0.0-alpha.7846284820",
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.7222542422",
31
+ "@applicaster/applicaster-types": "13.0.0-alpha.7846284820",
32
32
  "buffer": "^5.2.1",
33
33
  "camelize": "^1.0.0",
34
34
  "create-react-context": "^0.2.3",
@@ -5,7 +5,7 @@ const mockDimensionsGet = jest.fn(
5
5
  ({
6
6
  window: { width: 1, height: 1 },
7
7
  screen: { width: 360, height: 540 },
8
- }[type])
8
+ })[type]
9
9
  );
10
10
 
11
11
  ReactNative.Dimensions.get = mockDimensionsGet;
@@ -91,7 +91,7 @@ export function useLayoutConfiguration<
91
91
  S extends unknown,
92
92
  G extends unknown,
93
93
  R extends unknown,
94
- L extends unknown
94
+ L extends unknown,
95
95
  >(layoutData, manifest, options: Options = {}) {
96
96
  const keys = options.keys || [
97
97
  "assets",
@@ -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
- (eventName: string, handler?: (...args: unknown[]) => void): (
8
- ...args: unknown[]
9
- ) => ReturnType<typeof subscriber>;
7
+ (
8
+ eventName: string,
9
+ handler?: (...args: unknown[]) => void
10
+ ): (...args: unknown[]) => ReturnType<typeof subscriber>;
10
11
  }
11
12
 
12
13
  /**
@@ -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
- // const state = useState(screenState);
39
- const screenState = useScreenStore(
40
- path(["screens", screenId])
41
- ) as ScreenState;
42
+ const screenState = useScreenStore<ScreenState>(
43
+ useShallow(path(["screens", screenId]))
44
+ );
42
45
 
43
- const setSelectedEntry = useScreenStore((state) => state.setSelectedEntry);
46
+ const setSelectedEntry = useScreenStore<SetSelectedEntry>(
47
+ useShallow(path(["setSelectedEntry"]))
48
+ );
44
49
 
45
- if (!screenId) return null;
50
+ const memoizedSetSelectedEntry = React.useCallback(
51
+ (entryId) => setSelectedEntry(screenId, entryId),
52
+ [screenId, setSelectedEntry]
53
+ );
46
54
 
47
- return {
48
- screen: screenState,
49
- setSelectedEntry: (entryId) => setSelectedEntry(screenId, entryId),
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
 
package/time/Timer.ts CHANGED
@@ -3,7 +3,10 @@ export class Timer {
3
3
  private remaining: number;
4
4
  private timeoutId: NodeJS.Timeout | null;
5
5
 
6
- constructor(private callback: () => void, private duration: number) {
6
+ constructor(
7
+ private callback: () => void,
8
+ private duration: number
9
+ ) {
7
10
  this.remaining = this.duration;
8
11
  this.timeoutId = null;
9
12
  }
package/types.ts CHANGED
@@ -8,4 +8,5 @@ export type ManifestField<T> = {
8
8
 
9
9
  export enum ENDPOINT_TAGS {
10
10
  allow_missing_keys = "allow_missing_keys",
11
+ observe_storage = "observe_storage",
11
12
  }
@@ -92,9 +92,8 @@ export const PresentHookPluginOneTime = (
92
92
  const presentOneTimeVersionName =
93
93
  await getLatestWatchedVersionNumberFromStorage(storageKey, namespace);
94
94
 
95
- const applicationVersionName = await sessionStorage.getItem(
96
- versionNameKey
97
- );
95
+ const applicationVersionName =
96
+ await sessionStorage.getItem(versionNameKey);
98
97
 
99
98
  if (!presentOneTimeVersionName || !applicationVersionName) {
100
99
  log_info(
@@ -1,304 +0,0 @@
1
- // @ts-nocheck
2
- import utils from "../utils";
3
-
4
- describe("generateFontConfiguration", () => {
5
- it("should generate default configuration for tvos", () => {
6
- const expected = [
7
- {
8
- initial_value: 20,
9
- label: "tvOS font Size",
10
- key: "tvos_font_size",
11
- type: "number_input",
12
- },
13
- {
14
- initial_value: 40,
15
- label: "tvOS line Height",
16
- key: "tvos_line_height",
17
- type: "number_input",
18
- },
19
- {
20
- initial_value: 0.4,
21
- label: "tvOS letter Spacing",
22
- key: "tvos_letter_spacing",
23
- type: "number_input",
24
- },
25
- ];
26
-
27
- const platforms = {
28
- tvos: "tvOS",
29
- };
30
-
31
- const generatedFontConfiguration =
32
- utils.generateFontConfiguration(platforms);
33
-
34
- expect(generatedFontConfiguration).toEqual(expected);
35
- });
36
-
37
- it("should generate default configuration for android_tv", () => {
38
- const expected = [
39
- {
40
- initial_value: 20,
41
- label: "Android TV font Size",
42
- key: "android_tv_font_size",
43
- type: "number_input",
44
- },
45
- {
46
- initial_value: 40,
47
- label: "Android TV line Height",
48
- key: "android_tv_line_height",
49
- type: "number_input",
50
- },
51
- {
52
- initial_value: 0.4,
53
- label: "Android TV letter Spacing",
54
- key: "android_tv_letter_spacing",
55
- type: "number_input",
56
- },
57
- ];
58
-
59
- const platforms = {
60
- android_tv: "Android TV",
61
- };
62
-
63
- const generatedFontConfiguration =
64
- utils.generateFontConfiguration(platforms);
65
-
66
- expect(generatedFontConfiguration).toEqual(expected);
67
- });
68
-
69
- it("should generate default configuration for lg_tv", () => {
70
- const expected = [
71
- {
72
- initial_value: 20,
73
- label: "LG TV font Size",
74
- key: "lg_tv_font_size",
75
- type: "number_input",
76
- },
77
- {
78
- initial_value: 40,
79
- label: "LG TV line Height",
80
- key: "lg_tv_line_height",
81
- type: "number_input",
82
- },
83
- {
84
- initial_value: 0.4,
85
- label: "LG TV letter Spacing",
86
- key: "lg_tv_letter_spacing",
87
- type: "number_input",
88
- },
89
- ];
90
-
91
- const platforms = {
92
- lg_tv: "LG TV",
93
- };
94
-
95
- const generatedFontConfiguration =
96
- utils.generateFontConfiguration(platforms);
97
-
98
- expect(generatedFontConfiguration).toEqual(expected);
99
- });
100
-
101
- it("should generate default configuration for samsung_tv", () => {
102
- const expected = [
103
- {
104
- initial_value: 20,
105
- label: "Samsung TV font Size",
106
- key: "samsung_tv_font_size",
107
- type: "number_input",
108
- },
109
- {
110
- initial_value: 40,
111
- label: "Samsung TV line Height",
112
- key: "samsung_tv_line_height",
113
- type: "number_input",
114
- },
115
- {
116
- initial_value: 0.4,
117
- label: "Samsung TV letter Spacing",
118
- key: "samsung_tv_letter_spacing",
119
- type: "number_input",
120
- },
121
- ];
122
-
123
- const platforms = {
124
- samsung_tv: "Samsung TV",
125
- };
126
-
127
- const generatedFontConfiguration =
128
- utils.generateFontConfiguration(platforms);
129
-
130
- expect(generatedFontConfiguration).toEqual(expected);
131
- });
132
- });
133
-
134
- test("conditional_rule helper should return correct object", () => {
135
- expect(utils.conditional_rule("a", "b")).toMatchObject({
136
- key: "a",
137
- condition_value: "b",
138
- });
139
- });
140
-
141
- test("createConditionalConfig helper should return correct object", () => {
142
- expect(
143
- utils.createConditionalConfig([
144
- ["a", "b"],
145
- ["c", "d"],
146
- ])
147
- ).toEqual({
148
- rules: "conditional",
149
- conditional_fields: [
150
- {
151
- key: "a",
152
- condition_value: "b",
153
- },
154
- {
155
- key: "c",
156
- condition_value: "d",
157
- },
158
- ],
159
- });
160
- });
161
-
162
- test("conditional_horizontal_type should contain correct parameters", () => {
163
- expect(
164
- utils.conditional_horizontal_type_item_fixed.conditional_fields[0]
165
- ).toMatchObject({
166
- key: "styles/screen_picker_type",
167
- condition_value: "horizontal",
168
- });
169
- });
170
-
171
- test("conditional_vertical_type should contain correct parameters", () => {
172
- expect(utils.conditional_vertical_type.conditional_fields[0]).toMatchObject({
173
- key: "styles/screen_picker_type",
174
- condition_value: "vertical",
175
- });
176
- });
177
-
178
- test("conditional_horizontal_type_item_fixed should contain correct parameters", () => {
179
- expect(
180
- utils.conditional_horizontal_type_item_fixed.conditional_fields[0]
181
- ).toMatchObject({
182
- key: "styles/screen_picker_type",
183
- condition_value: "horizontal",
184
- });
185
-
186
- expect(
187
- utils.conditional_horizontal_type_item_fixed.conditional_fields[1]
188
- ).toMatchObject({
189
- key: "styles/screen_picker_item_size",
190
- condition_value: "fixed",
191
- });
192
- });
193
-
194
- test("conditional_horizontal_display_type_fixed should contain correct parameters", () => {
195
- expect(
196
- utils.conditional_horizontal_display_type_fixed.conditional_fields[0]
197
- ).toMatchObject({
198
- key: "styles/screen_picker_type",
199
- condition_value: "horizontal",
200
- });
201
-
202
- expect(
203
- utils.conditional_horizontal_display_type_fixed.conditional_fields[1]
204
- ).toMatchObject({
205
- key: "styles/screen_picker_horizontal_display_type",
206
- condition_value: "fixed",
207
- });
208
- });
209
-
210
- test("conditional_horizontal_display_type_fixed should contain correct parameters", () => {
211
- expect(
212
- utils.conditional_horizontal_asset_on.conditional_fields[0]
213
- ).toMatchObject({
214
- key: "styles/screen_picker_type",
215
- condition_value: "horizontal",
216
- });
217
-
218
- expect(
219
- utils.conditional_horizontal_asset_on.conditional_fields[1]
220
- ).toMatchObject({
221
- key: "styles/screen_picker_asset_switch",
222
- condition_value: true,
223
- });
224
- });
225
-
226
- describe("createVariationFields", () => {
227
- const defaultInput = {
228
- key: "somekey",
229
- label: "default somekey label",
230
- variants: [
231
- {
232
- initial_value: "a",
233
- },
234
- {
235
- initial_value: "b",
236
- label: "custom label",
237
- },
238
- ],
239
- };
240
-
241
- const config = utils.createVariationFields(defaultInput);
242
-
243
- it("should return array containing object for conditional_vertical_type", () => {
244
- expect(config[0].rules).toBe("conditional");
245
-
246
- expect(config[0].conditional_fields).toEqual([
247
- {
248
- key: "styles/screen_picker_type",
249
- condition_value: "vertical",
250
- },
251
- ]);
252
-
253
- expect(config[0].type).toBe("number_input");
254
- expect(config[0].key).toBe("screen_picker_vertical_somekey");
255
- expect(config[0].label).toBe("default somekey label");
256
- expect(config[0].initial_value).toBe("a");
257
- });
258
-
259
- it("should return array containing object for conditional_horizontal_type", () => {
260
- expect(config[1].rules).toBe("conditional");
261
-
262
- expect(config[1].conditional_fields).toEqual([
263
- {
264
- key: "styles/screen_picker_type",
265
- condition_value: "horizontal",
266
- },
267
- ]);
268
-
269
- expect(config[1].type).toBe("number_input");
270
- expect(config[1].key).toBe("screen_picker_horizontal_somekey");
271
- expect(config[1].label).toBe("custom label");
272
- expect(config[1].initial_value).toBe("b");
273
- });
274
-
275
- it("should accept custom prefix (empty)", () => {
276
- const config = utils.createVariationFields({
277
- ...defaultInput,
278
- prefix: "",
279
- });
280
-
281
- expect(config[0].key).toBe("vertical_somekey");
282
- expect(config[1].key).toBe("horizontal_somekey");
283
- });
284
-
285
- it("should accept custom prefix (string)", () => {
286
- const config = utils.createVariationFields({
287
- ...defaultInput,
288
- prefix: "string",
289
- });
290
-
291
- expect(config[0].key).toBe("string_vertical_somekey");
292
- expect(config[1].key).toBe("string_horizontal_somekey");
293
- });
294
-
295
- it("should accept custom type (string)", () => {
296
- const config = utils.createVariationFields({
297
- ...defaultInput,
298
- type: "text_input",
299
- });
300
-
301
- expect(config[0].type).toBe("text_input");
302
- expect(config[1].type).toBe("text_input");
303
- });
304
- });