@applicaster/zapp-react-native-bridge 11.0.0-rc.99 → 12.0.0-rc.1

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.
@@ -76,9 +76,9 @@ describe("remapAssetPath", () => {
76
76
  },
77
77
  ];
78
78
 
79
- const result = {
80
- "file://asset.jpg": true,
81
- "file://asset.png": true,
79
+ const result: Record<string, string> = {
80
+ "http://img.com/asset.jpg": "file://asset.jpg",
81
+ "http://img.com/asset.png": "file://asset.png",
82
82
  };
83
83
 
84
84
  expect(remapAssetPath(assets, config, result)).toMatchSnapshot();
@@ -97,7 +97,7 @@ describe("collectAssets", () => {
97
97
  },
98
98
  };
99
99
 
100
- expect(collectAssets(config, "/nativ/path", "files")).toMatchSnapshot();
100
+ expect(collectAssets(config, "/nativ/path", "files", [])).toMatchSnapshot();
101
101
  });
102
102
  });
103
103
 
@@ -3,6 +3,7 @@ import * as R from "ramda";
3
3
  import md5 from "md5";
4
4
 
5
5
  import { reducePromises } from "@applicaster/zapp-react-native-utils/arrayUtils";
6
+ import { bridgeLogger } from "../logger";
6
7
 
7
8
  const { OfflineAssetsBridge } = NativeModules as {
8
9
  OfflineAssetsBridge: OfflineAssetsBridgeI;
@@ -57,7 +58,7 @@ function getNativeFileName(nativeRootPath, url, path) {
57
58
  const fileNameWithoutQuery = url.split("?")[0];
58
59
  const extension = R.compose(R.last, R.split("."))(fileNameWithoutQuery);
59
60
 
60
- return `${nativeRootPath}/${path}/${md5(fileNameWithoutQuery)}.${extension}`;
61
+ return `${nativeRootPath}/${path}/${md5(url)}.${extension}`;
61
62
  }
62
63
 
63
64
  function propOrIndex(value) {
@@ -78,21 +79,45 @@ export const fileIsSaved = R.curry((savedFilesResult, { file }) => {
78
79
 
79
80
  export const remapAssetPath = (
80
81
  assets: FilesList,
81
- source: {},
82
- savedFilesResult?: StoredFilesResult
83
- ) =>
84
- R.reduce(
85
- (obj, { path, file, url }) =>
86
- R.set(
87
- R.lensPath(path),
88
- fileIsSaved(savedFilesResult, { file }) ? file : url,
89
- obj
90
- ),
91
- source,
92
- assets
93
- );
82
+ source: Record<string, any>,
83
+ localFiles: Record<string, string>
84
+ ): Record<string, any> => {
85
+ return assets.reduce((obj, { path, url }) => {
86
+ const localFile = localFiles[url];
87
+
88
+ if (!localFile) {
89
+ bridgeLogger.warning({
90
+ message: `remapAssetPath: Could not replace asset with local file for url: ${url}`,
91
+ data: { path, obj }});
92
+
93
+ return obj;
94
+ }
95
+
96
+ let target = obj;
97
+
98
+ // Traverse the path to the appropriate nested object
99
+ for (let i = 0; i < path.length - 1; i++) {
100
+ target = target[path[i]] = target[path[i]];
101
+ }
102
+
103
+ if (!target) {
104
+ bridgeLogger.error({message: `remapAssetPath: Could not find path ${path.join(".")}`, data: obj});
105
+ } else {
106
+ // Set the final value
107
+ target[path[path.length - 1]] = localFile;
108
+ }
109
+
110
+ return obj;
111
+ }, R.clone(source));
112
+ };
94
113
 
95
114
  export function collectAssets(object, nativeRootPath, source, path = []) {
115
+ if (!object) {
116
+ const message = `collectAssets: object is null or undefined for source: ${source}`;
117
+ bridgeLogger.error({ message, data: { object, path } });
118
+ throw new Error(message);
119
+ }
120
+
96
121
  return Object.entries(object).reduce((assets, [prop, value]) => {
97
122
  const propPath = [...path, propOrIndex(prop)];
98
123
 
@@ -0,0 +1,127 @@
1
+ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
2
+ import { BehaviorSubject } from "rxjs";
3
+ import { pushBridge } from "./index";
4
+
5
+ const {
6
+ registerTags: _registerTags,
7
+ unregisterTags: _unregisterTags,
8
+ getRegisteredTags: _getRegisteredTags,
9
+ } = pushBridge;
10
+
11
+ import { bridgeLogger } from "../logger";
12
+
13
+ export const { log_verbose, log_debug, log_warning, log_info, log_error } =
14
+ createLogger({
15
+ category: "PushTopicManager",
16
+ subsystem: "zapp-react-native-bridge",
17
+ parent: bridgeLogger,
18
+ });
19
+
20
+ export class PushTopicManager {
21
+ private registeredTags: string[] | null;
22
+ private pushTopicSubject: BehaviorSubject<string[] | null>;
23
+
24
+ constructor() {
25
+ void this.prepareTags();
26
+ }
27
+
28
+ getEntryObservable = (): BehaviorSubject<string[]> => {
29
+ return this.pushTopicSubject;
30
+ };
31
+
32
+ notifyTagsChange = () => {
33
+ this.pushTopicSubject.next(this.registeredTags);
34
+ };
35
+
36
+ prepareTags = async () => {
37
+ try {
38
+ this.pushTopicSubject = new BehaviorSubject(null);
39
+ this.registeredTags = await _getRegisteredTags();
40
+
41
+ log_debug(
42
+ `prepareTags: Current registered tags: '${this.registeredTags.join(
43
+ ","
44
+ )}'`
45
+ );
46
+
47
+ this.notifyTagsChange();
48
+ } catch (error) {
49
+ log_error(`prepareTags: Error while preparing tags: ${error.message}`, {
50
+ error,
51
+ });
52
+
53
+ throw error;
54
+ }
55
+ };
56
+
57
+ registerTags = async (tags: string[]) => {
58
+ try {
59
+ log_debug(
60
+ `registerTags: Native code will register new tags: '${tags.join(",")}'`
61
+ );
62
+
63
+ await _registerTags(tags);
64
+
65
+ this.registeredTags = this.registeredTags.concat(tags);
66
+
67
+ log_debug(
68
+ `registerTags: Tags were successfully registered. New list of existing tags: '${this.registeredTags.join(
69
+ ","
70
+ )}'. Notify subscribers`
71
+ );
72
+
73
+ this.notifyTagsChange();
74
+ } catch (error) {
75
+ log_error(
76
+ `registerTags: Error while registering tags: ${error.message}`,
77
+ { error }
78
+ );
79
+
80
+ throw error;
81
+ }
82
+ };
83
+
84
+ unregisterTags = async (tags: string[]) => {
85
+ try {
86
+ log_debug(
87
+ `unregisterTags: Native code will unregister new tags: '${tags.join(
88
+ ","
89
+ )}'`
90
+ );
91
+
92
+ await _unregisterTags(tags);
93
+
94
+ this.registeredTags = this.registeredTags.filter(
95
+ (tag) => !tags.includes(tag)
96
+ );
97
+
98
+ log_debug(
99
+ `unregisterTags: Tags were successfully unregistered. New list of existing tags: '${this.registeredTags.join(
100
+ ","
101
+ )}'. Notify subscribers`
102
+ );
103
+
104
+ this.notifyTagsChange();
105
+ } catch (error) {
106
+ log_error(
107
+ `unregisterTags: Error while unregistering tags: ${error.message}`,
108
+ { error }
109
+ );
110
+
111
+ throw error;
112
+ }
113
+ };
114
+
115
+ getRegisteredTags = () => {
116
+ return this.registeredTags;
117
+ };
118
+
119
+ private static instance: PushTopicManager;
120
+ public static getInstance() {
121
+ if (!PushTopicManager.instance) {
122
+ PushTopicManager.instance = new PushTopicManager();
123
+ }
124
+
125
+ return PushTopicManager.instance;
126
+ }
127
+ }
@@ -22,7 +22,7 @@ const { PushBridge = defaultPushNotification } = NativeModules as {
22
22
  export const pushBridge = {
23
23
  /**
24
24
  * Register push tags to push notification provider
25
- * @param {String} tags Tags array to reginster
25
+ * @param {String} tags Tags array to register
26
26
  */
27
27
  async registerTags(tags) {
28
28
  return PushBridge.registerTags(tags);
@@ -30,7 +30,7 @@ export const pushBridge = {
30
30
 
31
31
  /**
32
32
  * Unregister push tags to push notification provider
33
- * @param {String} tags Tags array to reginster
33
+ * @param {String} tags Tags array to register
34
34
  */
35
35
  async unregisterTags(tags) {
36
36
  return PushBridge.unregisterTags(tags);
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as R from "ramda";
3
2
  import { Platform } from "react-native";
4
3
  import uuidv4 from "uuid/v4";
@@ -0,0 +1,153 @@
1
+ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
2
+ import { bridgeLogger } from "../logger";
3
+ import { BehaviorSubject } from "rxjs";
4
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
5
+ import { getNamespaceAndKey } from "@applicaster/zapp-react-native-utils/appUtils/contextKeysManager/utils";
6
+
7
+ export const { log_verbose, log_debug, log_warning, log_info, log_error } =
8
+ createLogger({
9
+ category: "StorageMultiSelectProvider",
10
+ subsystem: "zapp-react-native-bridge",
11
+ parent: bridgeLogger,
12
+ });
13
+
14
+ export interface MultiSelectProvider {
15
+ getObservable(): BehaviorSubject<string[]>;
16
+
17
+ addItem(item: string): Promise<void>;
18
+
19
+ addItems(items: string[]): Promise<void>;
20
+
21
+ setSelectedItems(items: string[]): Promise<void>;
22
+
23
+ removeItem(item: string): Promise<void>;
24
+
25
+ removeItems(items: string[]): Promise<void>;
26
+
27
+ removeAllItems(): Promise<void>;
28
+
29
+ getSelectedItems(): string[];
30
+
31
+ getSelectedAsync(): Promise<string[]>;
32
+ }
33
+
34
+ export class StorageMultiSelectProvider implements MultiSelectProvider {
35
+ // TODO: Unsubscribe and remove when there is no listeners
36
+ private static multiSelectProviders: Record<string, StorageMultiSelectProvider> = {};
37
+
38
+ public static getProvider(keyNamespace:string): StorageMultiSelectProvider {
39
+ if (!this.multiSelectProviders[keyNamespace]) {
40
+ this.multiSelectProviders[keyNamespace] = new StorageMultiSelectProvider(keyNamespace);
41
+ }
42
+
43
+ return this.multiSelectProviders[keyNamespace];
44
+ }
45
+
46
+ private itemSubject: BehaviorSubject<string[] | null>;
47
+
48
+ private readonly key:string
49
+ private readonly namespace:string;
50
+
51
+ private constructor(keyNamespace: string) {
52
+ const { namespace, key } = getNamespaceAndKey(keyNamespace);
53
+
54
+ if (!key) {
55
+ throw new Error("StorageMultiSelectProvider: Key is required");
56
+ }
57
+
58
+ this.key = key;
59
+ this.namespace = namespace;
60
+ localStorage.addListener?.({ key, namespace }, this.reloadItems);
61
+
62
+ this.itemSubject = new BehaviorSubject([]);
63
+
64
+ void this.getSelectedAsync();
65
+ log_debug("StorageMultiSelectProvider: Initializing");
66
+ }
67
+
68
+ private reloadItems = async ({ value }:StorageListenerArgs) => {
69
+ const selectedItems = value ? value.split(",") : [];
70
+
71
+ log_debug(`reloadItems: request to reload items for value: ${value}`, selectedItems);
72
+
73
+ this.itemSubject.next(selectedItems);
74
+ };
75
+
76
+ public getObservable = (): BehaviorSubject<string[]> => this.itemSubject;
77
+
78
+ private async getSetOfCurrentItems() {
79
+ const currentResult: string = await localStorage.getItem(this.key, this.namespace);
80
+
81
+ return new Set(currentResult ? currentResult.split(",") : []);
82
+ }
83
+
84
+ private async updateItemsAndNotifyObservers(currentItems: Set<string>) {
85
+ const arrayOfItems = Array.from(currentItems);
86
+ const newValue = arrayOfItems.join(",");
87
+ await localStorage.setItem(this.key, newValue, this.namespace);
88
+
89
+ this.itemSubject.next(arrayOfItems);
90
+ }
91
+
92
+ public addItem = async(item: string): Promise<void> => {
93
+ const currentItems = await this.getSetOfCurrentItems();
94
+ currentItems.add(item);
95
+ log_debug(`addItem: Adding new item: ${item}`);
96
+
97
+ await this.updateItemsAndNotifyObservers(currentItems);
98
+ }
99
+
100
+ public addItems = async(items: string[]): Promise<void> => {
101
+ const currentItems = await this.getSetOfCurrentItems();
102
+
103
+ items.forEach((item) => currentItems.add(item));
104
+
105
+ log_debug(`addItems: Adding new items: ${items.join(",")}, current items: ${Array.from(currentItems).join(",")}`);
106
+
107
+ await this.updateItemsAndNotifyObservers(currentItems);
108
+ }
109
+
110
+ public removeItem = async(item: string): Promise<void> => {
111
+ const currentItems = await this.getSetOfCurrentItems();
112
+ currentItems.delete(item);
113
+
114
+ log_debug(`removeItem: Removing item: ${item}, current items: ${Array.from(currentItems).join(",")}`);
115
+
116
+ await this.updateItemsAndNotifyObservers(currentItems);
117
+ }
118
+
119
+ public removeItems = async (items: string[]): Promise<void> => {
120
+ const currentItems = await this.getSetOfCurrentItems();
121
+
122
+ items.forEach((item) => currentItems.delete(item));
123
+
124
+ log_debug(`removeItems: Removing items: ${items.join(",")}, current items: ${Array.from(currentItems).join(",")}`);
125
+
126
+ await this.updateItemsAndNotifyObservers(currentItems);
127
+ }
128
+
129
+ public removeAllItems = async (): Promise<void> => {
130
+ await localStorage.removeItem(this.key, this.namespace);
131
+ log_debug(`removeAllItems: Removing all items, current items: ${[]}`);
132
+
133
+ this.itemSubject.next([]);
134
+ }
135
+
136
+ public getSelectedAsync = async (): Promise<string[]> => {
137
+ const value = await localStorage.getItem(this.key, this.namespace);
138
+ const selectedItems = value ? value.split(",") : [];
139
+ this.itemSubject.next(selectedItems);
140
+
141
+ return selectedItems;
142
+ }
143
+
144
+ public getSelectedItems = (): string[] => {
145
+ return this.itemSubject.getValue();
146
+ }
147
+
148
+ setSelectedItems = async (items: string[]): Promise<void> => {
149
+ log_debug(`setSelectedItems: Setting selected items: ${items.join(",")}`);
150
+
151
+ await this.updateItemsAndNotifyObservers(new Set(items));
152
+ }
153
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-bridge",
3
- "version": "11.0.0-rc.99",
3
+ "version": "12.0.0-rc.1",
4
4
  "description": "Applicaster Zapp React Native modules",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "homepage": "https://github.com/applicaster/quickbrick#readme",
34
34
  "dependencies": {
35
35
  "@applicaster/zapp-pipes-dev-kit": "1.4.7",
36
- "@applicaster/zapp-react-native-utils": "11.0.0-rc.99",
36
+ "@applicaster/zapp-react-native-utils": "12.0.0-rc.1",
37
37
  "md5": "^2.3.0",
38
38
  "uuid": "^3.3.2"
39
39
  },