@applicaster/zapp-react-native-utils 12.0.0-alpha.3964644693 → 12.0.0-alpha.4043183114

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.
Files changed (39) hide show
  1. package/appUtils/HooksManager/{Hook.js → Hook.ts} +17 -11
  2. package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
  3. package/appUtils/HooksManager/{index.js → index.ts} +98 -109
  4. package/appUtils/HooksManager/types.ts +93 -0
  5. package/appUtils/RiverFocusManager/index.js +17 -12
  6. package/appUtils/accessibilityManager/const.ts +50 -0
  7. package/appUtils/accessibilityManager/hooks.ts +31 -0
  8. package/appUtils/accessibilityManager/index.ts +150 -0
  9. package/appUtils/accessibilityManager/logger.ts +5 -0
  10. package/appUtils/focusManager/index.ts +0 -1
  11. package/appUtils/focusManager/treeDataStructure/Tree/index.js +2 -3
  12. package/appUtils/focusManager/treeDataStructure/Utils/index.js +2 -4
  13. package/appUtils/{index.js → index.ts} +2 -0
  14. package/appUtils/keyCodes/{index.js → index.ts} +2 -0
  15. package/appUtils/keyCodes/keys/index.ts +3 -0
  16. package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
  17. package/appUtils/keyCodes/keys/keys.android.ts +18 -0
  18. package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
  19. package/appUtils/keyCodes/keys/keys.ts +15 -0
  20. package/appUtils/platform/platformUtils.ts +40 -92
  21. package/appUtils/playerManager/conts.ts +1 -0
  22. package/appUtils/playerManager/player.ts +9 -0
  23. package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -0
  24. package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
  25. package/functionUtils/index.ts +15 -11
  26. package/modalState/index.ts +1 -5
  27. package/navigationUtils/index.ts +62 -5
  28. package/package.json +2 -2
  29. package/pluginUtils/index.ts +9 -0
  30. package/reactHooks/navigation/index.ts +11 -4
  31. package/reactUtils/index.ts +0 -11
  32. package/appUtils/keyCodes/keys.ios.js +0 -46
  33. /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
  34. /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
  35. /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
  36. /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
  37. /package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +0 -0
  38. /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
  39. /package/domUtils/{logger.js → logger.ts} +0 -0
@@ -4,6 +4,7 @@ import { isFunction } from "../../functionUtils";
4
4
  import { HOOKS_EVENTS, HOOKS_TRANSITION_TYPE } from "./constants";
5
5
 
6
6
  import { hooksManagerLogger } from "./logger";
7
+ import type { Hook as HookInterface, HookIniObj } from "./types";
7
8
 
8
9
  const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
9
10
 
@@ -14,7 +15,9 @@ const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
14
15
  * @param {string} hookEventName
15
16
  * @returns {number} index
16
17
  */
17
- const hookState = R.indexOf(R.__, R.values(HOOKS_EVENTS));
18
+ const hookState: (
19
+ arg0: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS]
20
+ ) => number = R.indexOf(R.__, R.values(HOOKS_EVENTS));
18
21
 
19
22
  /**
20
23
  * assigns property to a given context
@@ -28,17 +31,20 @@ function assignProp(context) {
28
31
  }
29
32
 
30
33
  /**
31
- * Representation of a hook plugin with full data
34
+ * Representation of a hook plugin
32
35
  */
33
- export class Hook {
34
- /**
35
- * constructs the hook
36
- * @param {object} Options
37
- * @param {object} Options.hook hook object
38
- * @param {Array<Object>} Options.hooks array of hooks siblings in the current process
39
- * @param {object} manager hook manager to process the hooks
40
- */
41
- constructor({ hook, hooks, manager }) {
36
+ export class Hook implements HookInterface {
37
+ public manager;
38
+ public lastHook;
39
+ public state;
40
+ public screen_id;
41
+ public identifier;
42
+ public module;
43
+ public general;
44
+ public weight;
45
+ public configuration;
46
+
47
+ constructor({ hook, hooks, manager }: HookIniObj) {
42
48
  R.forEachObjIndexed(assignProp(this), hook);
43
49
  this.manager = manager;
44
50
 
@@ -12,7 +12,7 @@ export const HOOKS_EVENTS = {
12
12
  CANCEL: "cancel",
13
13
  SUCCESS: "success",
14
14
  COMPLETE: "complete",
15
- };
15
+ } as const;
16
16
 
17
17
  export const HOOKS_TRANSITION_TYPE = {
18
18
  PUSH: "push",
@@ -10,14 +10,68 @@ import { Hook } from "./Hook";
10
10
  import { HOOKS_EVENTS, HOOKS_TYPE } from "./constants";
11
11
 
12
12
  import { hooksManagerLogger } from "./logger";
13
+ import { HookManager, HookManagerArgs } from "./types";
14
+
15
+ /**
16
+ * orders the hooks according to their weight
17
+ * @param {Array<object>} hooks to sort out
18
+ * @returns {Array<object>} sorted hooks
19
+ */
20
+ function orderHooksByWeight(hooks) {
21
+ return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
22
+ }
23
+
24
+ function executeOnNextHook(hooks, payload, callback) {
25
+ const [nextHook, ...restOfHooks] = orderHooksByWeight(hooks);
26
+
27
+ if (nextHook) {
28
+ nextHook.execute(payload, callback(nextHook, restOfHooks, payload));
29
+ }
30
+ }
31
+
32
+ /**
33
+ * tells wether the current river is related to a player plugin, or the default player
34
+ * @param {Object} river
35
+ * @returns {boolean}
36
+ */
37
+ function riverIsPlayer(river, plugins) {
38
+ const { screenType, plugin_type } = river;
39
+
40
+ if (screenType || plugin_type) {
41
+ return screenType === "playable" || plugin_type === "player";
42
+ }
43
+
44
+ const { type } = river;
45
+
46
+ return R.compose(
47
+ R.propEq("type", "player"),
48
+ R.defaultTo({}),
49
+ R.find(R.propEq("identifier", type))
50
+ )(plugins);
51
+ }
52
+
53
+ /**
54
+ * Injects the hooks for the player
55
+ * @param _hookType type of hook
56
+ * @param plugins plugins
57
+ * @returns {Array<Object>}
58
+ */
59
+ function injectPlayerHooks(_hookType: string, plugins): Hook[] {
60
+ const playerhooks: Hook[] = R.compose(
61
+ R.sortBy(R.prop("weight")),
62
+ R.map((plugin) => ({
63
+ identifier: plugin.identifier,
64
+ weight: R.path(["module", "weight"], plugin) || 1,
65
+ })),
66
+ R.filter(R.pathEq(["module", "hasPlayerHook"], true))
67
+ )(plugins);
68
+
69
+ return playerhooks;
70
+ }
13
71
 
14
72
  /**
15
73
  * creates a hooksManager object to handle the hooks process.
16
74
  * it is based on the `subscriber` object
17
- * @param {object} options
18
- * @param {object} rivers map of rivers in the app
19
- * @param {object} targetScreen rivers which we are navigating to
20
- * @param {Array<object>} plugins array of plugins in the app
21
75
  * @returns {object} hooksManager object - see Navigator for usage
22
76
  */
23
77
  export function HooksManager({
@@ -25,7 +79,7 @@ export function HooksManager({
25
79
  targetScreen,
26
80
  plugins,
27
81
  startUpHooksData = {},
28
- }) {
82
+ }: HookManagerArgs): HookManager {
29
83
  hooksManagerLogger.addContext({ targetScreen });
30
84
 
31
85
  function logHookEvent(func, message, data) {
@@ -35,7 +89,8 @@ export function HooksManager({
35
89
  });
36
90
  }
37
91
 
38
- const hooksManager = subscriber();
92
+ const hooksManager: Partial<HookManager> = {};
93
+ hooksManager.subscriber = subscriber();
39
94
 
40
95
  /**
41
96
  * attaches the screen data to the hook object if the hook
@@ -100,15 +155,6 @@ export function HooksManager({
100
155
  };
101
156
  }
102
157
 
103
- /**
104
- * orders the hooks according to their weight
105
- * @param {Array<object>} hooks to sort out
106
- * @returns {Array<object>} sorted hooks
107
- */
108
- function orderHooksByWeight(hooks) {
109
- return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
110
- }
111
-
112
158
  /**
113
159
  * extracts the hooks form the target river. returns null if there are none
114
160
  * if there are hooks, gathers all required data and constructs a Hook object
@@ -117,10 +163,10 @@ export function HooksManager({
117
163
  * @returns {Array<Hooks>} list of hooks to go through
118
164
  */
119
165
  function getHooks(hookType, river) {
120
- const playerhooks = [];
166
+ const playerhooks: Hook[] = [];
121
167
 
122
- if (riverIsPlayer(river)) {
123
- playerhooks.push(...injectPlayerHooks(hookType));
168
+ if (riverIsPlayer(river, plugins)) {
169
+ playerhooks.push(...injectPlayerHooks(hookType, plugins));
124
170
  }
125
171
 
126
172
  let hooks = R.concat(playerhooks, R.pathOr([], ["hooks", hookType], river));
@@ -130,8 +176,10 @@ export function HooksManager({
130
176
  const { startUpHooks, setStartUpHooks } = startUpHooksData;
131
177
 
132
178
  if (startUpHooks && startUpHooks !== "in_process") {
133
- hooks.unshift(...startUpHooks);
134
- setStartUpHooks("in_process");
179
+ if (Array.isArray(startUpHooks)) {
180
+ hooks.unshift(...startUpHooks);
181
+ setStartUpHooks("in_process");
182
+ }
135
183
  }
136
184
 
137
185
  if (!R.length(hooks)) {
@@ -158,45 +206,6 @@ export function HooksManager({
158
206
  )(hooks);
159
207
  }
160
208
 
161
- /**
162
- * tells wether the current river is related to a player plugin, or the default player
163
- * @param {Object} river
164
- * @returns {boolean}
165
- */
166
- function riverIsPlayer(river) {
167
- const { screenType, plugin_type } = river;
168
-
169
- if (screenType || plugin_type) {
170
- return screenType === "playable" || plugin_type === "player";
171
- }
172
-
173
- const { type } = river;
174
-
175
- return R.compose(
176
- R.propEq("type", "player"),
177
- R.defaultTo({}),
178
- R.find(R.propEq("identifier", type))
179
- )(plugins);
180
- }
181
-
182
- /**
183
- * Injects the hooks for the player
184
- * @param {String} hookType type of hook
185
- * @returns {Array<Object>}
186
- */
187
- function injectPlayerHooks(_hookType) {
188
- const playerhooks = R.compose(
189
- R.sortBy(R.prop("weight")),
190
- R.map((plugin) => ({
191
- identifier: plugin.identifier,
192
- weight: R.path(["module", "weight"], plugin) || 1,
193
- })),
194
- R.filter(R.pathEq(["module", "hasPlayerHook"], true))
195
- )(plugins);
196
-
197
- return playerhooks;
198
- }
199
-
200
209
  /**
201
210
  * tells wether the given hook is the last one or not
202
211
  * @param {Hook} hookPlugin
@@ -209,6 +218,32 @@ export function HooksManager({
209
218
  return hookPlugin.lastHook;
210
219
  }
211
220
 
221
+ /**
222
+ * flags a hook as succeeded, and pass hook data along
223
+ * @param {Hook} hookPlugin
224
+ * @param {object} payload returned by the hook plugin
225
+ */
226
+ function completeHook(hookPlugin, payload, callback) {
227
+ logHookEvent(
228
+ hooksManagerLogger.info,
229
+ `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
230
+ {
231
+ payload,
232
+ hook: hookPlugin,
233
+ }
234
+ );
235
+
236
+ // eslint-disable-next-line
237
+ // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
238
+ delete payload.getLoginProtocol;
239
+
240
+ hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
241
+ hookPlugin,
242
+ payload,
243
+ callback,
244
+ });
245
+ }
246
+
212
247
  /**
213
248
  * creates the callback to invoke in order to proceed to the next hook
214
249
  * covers the scenarios of failure & flow blocking
@@ -309,37 +344,11 @@ export function HooksManager({
309
344
 
310
345
  isLastHook(hookPlugin, restOfHooks)
311
346
  ? completeHook(hookPlugin, payload, callback)
312
- : handleNextHook(restOfHooks, payload);
347
+ : executeOnNextHook(restOfHooks, payload, callback);
313
348
  }
314
349
  };
315
350
  }
316
351
 
317
- /**
318
- * flags a hook as succeeded, and pass hook data along
319
- * @param {Hook} hookPlugin
320
- * @param {object} payload returned by the hook plugin
321
- */
322
- function completeHook(hookPlugin, payload, callback) {
323
- logHookEvent(
324
- hooksManagerLogger.info,
325
- `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
326
- {
327
- payload,
328
- hook: hookPlugin,
329
- }
330
- );
331
-
332
- // eslint-disable-next-line
333
- // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
334
- delete payload.getLoginProtocol;
335
-
336
- hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
337
- hookPlugin,
338
- payload,
339
- callback,
340
- });
341
- }
342
-
343
352
  /**
344
353
  * presents a screen hook by triggering an event invoking the handler with
345
354
  * the appropriate route & payload
@@ -376,9 +385,6 @@ export function HooksManager({
376
385
 
377
386
  /**
378
387
  * executes a headless hook
379
- * @param {Hook} hookPlugin to present
380
- * @param {object} payload to pass to the hook module
381
- * @param {function} callback to invoke when the hook is successful
382
388
  */
383
389
  hooksManager.executeHook = function (hookPlugin, payload, callback) {
384
390
  logHookEvent(
@@ -444,23 +450,6 @@ export function HooksManager({
444
450
  }
445
451
  };
446
452
 
447
- /**
448
- * handles the next hook in the list of provided hooks, passing the payload along
449
- * @param {Array<Hook>} hooks to process
450
- * @param {object} payload to pass to the hook
451
- */
452
- function handleNextHook(hooks, payload) {
453
- const [hookPlugin, ...restOfHooks] = orderHooksByWeight(hooks);
454
-
455
- /**
456
- * Commenting out part of the code which is trying to run the next hook
457
- * in parallel - it's not in use, and it's creating unexpected side
458
- * effects
459
- * */
460
-
461
- hookPlugin.execute(payload, hookCallback(hookPlugin, restOfHooks, payload));
462
- }
463
-
464
453
  /**
465
454
  * function exposes on the hooks manager to trigger the handling of the hooks for
466
455
  * the given targetScreen
@@ -482,9 +471,9 @@ export function HooksManager({
482
471
  }
483
472
  );
484
473
 
485
- handleNextHook(preloadHooks, payload);
474
+ executeOnNextHook(preloadHooks, payload, hookCallback);
486
475
  } else {
487
- hooksManager.invokeHandler(HOOKS_EVENTS.COMPLETE, {
476
+ hooksManager.subscriber.invokeHandler(HOOKS_EVENTS.COMPLETE, {
488
477
  hookPlugin: { lastHook: true },
489
478
  payload,
490
479
  });
@@ -493,5 +482,5 @@ export function HooksManager({
493
482
  return hooksManager;
494
483
  };
495
484
 
496
- return hooksManager;
485
+ return hooksManager as HookManager;
497
486
  }
@@ -0,0 +1,93 @@
1
+ import { SubscriberObj } from "../../functionUtils";
2
+ import { HOOKS_EVENTS } from "./constants";
3
+
4
+ export interface HookConfiguration {}
5
+
6
+ export interface HookModule {
7
+ ModalContainer: React.ComponentType<any>;
8
+ Component: React.ComponentType<any>;
9
+ presentFullScreen: boolean;
10
+ run: (
11
+ arg0: unknown,
12
+ callback: () => void,
13
+ configuration: HookConfiguration
14
+ ) => void;
15
+ configuration: HookConfiguration;
16
+ isFlowBlocker: () => boolean;
17
+ skipHook: boolean;
18
+ setSkipHook: (skipHook: boolean) => void;
19
+ shouldSkipHook: () => boolean;
20
+ runInBackground: (
21
+ arg0: unknown,
22
+ callback: () => void,
23
+ hookPlugin: Hook,
24
+ presentUI: boolean
25
+ ) => void;
26
+ }
27
+
28
+ export type HookManagerArgs = {
29
+ rivers: Record<string, ZappRiver>;
30
+ plugins: ZappPlugin[];
31
+ targetScreen: ZappRiver;
32
+ startUpHooksData?: {
33
+ startUpHooks?: unknown[] | "in_process";
34
+ setStartUpHooks?: (arg0: string) => void;
35
+ };
36
+ };
37
+
38
+ export interface HookManager {
39
+ subscriber: SubscriberObj;
40
+ presentScreenHook: (
41
+ hook: Hook,
42
+ payload: unknown,
43
+ callback: (...any) => void
44
+ ) => void;
45
+ executeHook: (
46
+ hook: Hook,
47
+ payload: unknown,
48
+ callback: (...any) => void
49
+ ) => void;
50
+ handleHooks: (payload: unknown) => void;
51
+ runInBackground: (
52
+ hook: Hook,
53
+ payload: unknown,
54
+ callback: (...any) => void,
55
+ presentUI: boolean
56
+ ) => void;
57
+ }
58
+
59
+ export type HookIniObj = {
60
+ hook: HookModule & {
61
+ module: HookModule;
62
+ general: unknown;
63
+ screen_id?: string;
64
+ identifier?: string;
65
+ weight?: number | string;
66
+ };
67
+ hooks: Hook<any>[];
68
+ manager: HookManager;
69
+ };
70
+
71
+ export interface Hook<T extends HookModule = HookModule> {
72
+ manager: HookManager;
73
+ lastHook: boolean;
74
+ state: number;
75
+ module: T;
76
+ screen_id: string;
77
+ identifier: string;
78
+ configuration: T["configuration"];
79
+ setStateAndNotify(
80
+ event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
81
+ opts: {
82
+ error?: typeof Error;
83
+ route?: string;
84
+ hookPlugin: Hook<T>;
85
+ payload: unknown;
86
+ }
87
+ );
88
+ general?: {
89
+ transition_type: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS];
90
+ allow_screen_plugin_presentation: boolean;
91
+ is_flow_blocker: boolean;
92
+ };
93
+ }
@@ -26,7 +26,7 @@ export const riverFocusManager = (function () {
26
26
  /**
27
27
  * Retrieve screen focus data by id
28
28
  *
29
- * @param {String} screenFocusableGroupId Id that was used to save screen data.
29
+ * @param {{screenFocusableGroupId: string}} screenFocusableGroupId Unique Id of the screen from layout.json
30
30
  *
31
31
  */
32
32
  function screenFocusableData({ screenFocusableGroupId }) {
@@ -36,8 +36,9 @@ export const riverFocusManager = (function () {
36
36
  /**
37
37
  * Clear screen data for specific screen
38
38
  *
39
- * @param {String} screenId Unique Id of the screen from layout.json
40
- * @param {boolean} isInsideContainer If this screen a screen picker child
39
+ * @param {{ screenId: string, isInsideContainer: boolean }}
40
+ * screenId Unique Id of the screen from layout.json
41
+ * isInsideContainer If this screen a screen picker child
41
42
  *
42
43
  */
43
44
  function clearScreenData({ screenId, isInsideContainer }) {
@@ -60,9 +61,13 @@ export const riverFocusManager = (function () {
60
61
  /**
61
62
  * Focus on selected items
62
63
  *
63
- * @param {String} screenFocusableGroupId Top group id that was saved as screenn
64
- * @param {String} screenFocusedOnItem focusable item to focus
65
- * @param {object} history navigator history object
64
+ * @param {{
65
+ * screenFocusableGroupId: string,
66
+ * screenFocusedOnItem: () => void,
67
+ * previousAction: QuickBrickNavigationActionType,
68
+ * isDeepLink: boolean }} object contains data for focus
69
+ * - `screenFocusedOnItem` focusable item to focus
70
+ * - `previousActionhistory` navigator history object
66
71
  *
67
72
  */
68
73
  function focusOnSelectedItem({
@@ -115,15 +120,15 @@ export const riverFocusManager = (function () {
115
120
 
116
121
  /**
117
122
  * Create unique key that will be used for save focused group data inside specific screen
118
- *
119
- * @param {String} screenId Unique Id of the screen from layout.json
120
- * @param {boolean} isInsideContainer If this screen a screen picker child
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
121
126
  *
122
127
  */
123
128
  function screenFocusableGroupId({ screenId, isInsideContainer }) {
124
- return R.isNil(isInsideContainer)
125
- ? `RiverFocusableGroup-${screenId}`
126
- : `RiverFocusableGroup-${screenId}-isInsideContainer`;
129
+ return `RiverFocusableGroup-${screenId}${
130
+ R.isNil(isInsideContainer) ? "" : "-isInsideContainer"
131
+ }`;
127
132
  }
128
133
 
129
134
  return {
@@ -0,0 +1,50 @@
1
+ export const BUTTON_ACCESSIBILITY_KEYS = {
2
+ play: {
3
+ label: "accessibility_play_label",
4
+ hint: "accessibility_play_hint",
5
+ mini: {
6
+ label: "accessibility_play_mini_label",
7
+ hint: "accessibility_play_mini_hint",
8
+ },
9
+ },
10
+ pause: {
11
+ label: "accessibility_pause_label",
12
+ hint: "accessibility_pause_hint",
13
+ mini: {
14
+ label: "accessibility_pause_mini_label",
15
+ hint: "accessibility_pause_mini_hint",
16
+ },
17
+ },
18
+ rewind: {
19
+ label: "accessibility_rewind_label",
20
+ hint: "accessibility_rewind_hint",
21
+ },
22
+ forward: {
23
+ label: "accessibility_forward_label",
24
+ hint: "accessibility_forward_hint",
25
+ },
26
+ close: {
27
+ label: "accessibility_close_label",
28
+ hint: "accessibility_close_hint",
29
+ mini: {
30
+ label: "accessibility_close_mini_label",
31
+ hint: "accessibility_close_mini_hint",
32
+ },
33
+ },
34
+ maximize: {
35
+ label: "accessibility_maximize_label",
36
+ hint: "accessibility_maximize_hint",
37
+ },
38
+ subtitles: {
39
+ label: "accessibility_subtitle_label",
40
+ hint: "accessibility_subtitle_hint",
41
+ },
42
+ back: {
43
+ label: "accessibility_back_label",
44
+ hint: "accessibility_back_hint",
45
+ },
46
+ fullscreen: {
47
+ label: "accessibility_fullscreen_label",
48
+ hint: "accessibility_fullscreen_hint",
49
+ },
50
+ } as const;
@@ -0,0 +1,31 @@
1
+ import { useEffect, useMemo } from "react";
2
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import { AccessibilityManager } from "./index";
4
+
5
+ export const useAccessibilityManager = () => {
6
+ const { remoteConfigurations } = usePickFromState(["remoteConfigurations"]);
7
+ const { localizations } = remoteConfigurations;
8
+
9
+ const accessibilityManager = useMemo(() => {
10
+ return AccessibilityManager.getInstance();
11
+ }, []);
12
+
13
+ useEffect(() => {
14
+ accessibilityManager.updateLocalizations(localizations);
15
+ }, [localizations]);
16
+
17
+ useEffect(() => {
18
+ const subscription = accessibilityManager.getStateAsObservable().subscribe({
19
+ next: () => {
20
+ // TODO: handle accessibility states
21
+ // screenReaderEnabled: false
22
+ // reduceMotionEnabled: false
23
+ // boldTextEnabled: false
24
+ },
25
+ });
26
+
27
+ return () => subscription.unsubscribe();
28
+ }, [accessibilityManager]);
29
+
30
+ return accessibilityManager;
31
+ };