UNPKG

@applicaster/zapp-react-native-bridge

Version:

Applicaster Zapp React Native modules

177 lines (128 loc) • 5.23 kB
import { createLogger } from "@applicaster/zapp-react-native-utils/logger"; import { bridgeLogger } from "../logger"; import { BehaviorSubject } from "rxjs"; import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage"; import { getNamespaceAndKey } from "@applicaster/zapp-react-native-utils/appUtils/contextKeysManager/utils"; export const { log_verbose, log_debug, log_warning, log_info, log_error } = createLogger({ category: "StorageMultiSelectProvider", subsystem: "zapp-react-native-bridge", parent: bridgeLogger, }); export interface MultiSelectProvider { getObservable(): BehaviorSubject<string[]>; addItem(item: string): Promise<void>; addItems(items: string[]): Promise<void>; setSelectedItems(items: string[]): Promise<void>; removeItem(item: string): Promise<void>; removeItems(items: string[]): Promise<void>; removeAllItems(): Promise<void>; getSelectedItems(): string[]; getSelectedAsync(): Promise<string[]>; } export class StorageMultiSelectProvider implements MultiSelectProvider { // TODO: Unsubscribe and remove when there is no listeners private static multiSelectProviders: Record< string, StorageMultiSelectProvider > = {}; public static getProvider(keyNamespace: string): StorageMultiSelectProvider { if (!this.multiSelectProviders[keyNamespace]) { this.multiSelectProviders[keyNamespace] = new StorageMultiSelectProvider( keyNamespace ); } return this.multiSelectProviders[keyNamespace]; } private itemSubject: BehaviorSubject<string[] | null>; private readonly key: string; private readonly namespace: string; private constructor(keyNamespace: string) { const { namespace, key } = getNamespaceAndKey(keyNamespace); if (!key) { throw new Error("StorageMultiSelectProvider: Key is required"); } this.key = key; this.namespace = namespace; localStorage.addListener?.({ key, namespace }, this.reloadItems); this.itemSubject = new BehaviorSubject([]); void this.getSelectedAsync(); log_debug("StorageMultiSelectProvider: Initializing"); } private reloadItems = async ({ value }: StorageListenerArgs) => { const selectedItems = value ? value.split(",") : []; log_debug( `reloadItems: request to reload items for value: ${value}`, selectedItems ); this.itemSubject.next(selectedItems); }; public getObservable = (): BehaviorSubject<string[]> => this.itemSubject; private async getSetOfCurrentItems() { const currentResult: string = await localStorage.getItem( this.key, this.namespace ); return new Set(currentResult ? currentResult.split(",") : []); } private async updateItemsAndNotifyObservers(currentItems: Set<string>) { const arrayOfItems = Array.from(currentItems); const newValue = arrayOfItems.join(","); await localStorage.setItem(this.key, newValue, this.namespace); this.itemSubject.next(arrayOfItems); } public addItem = async (item: string): Promise<void> => { const currentItems = await this.getSetOfCurrentItems(); currentItems.add(item); log_debug(`addItem: Adding new item: ${item}`); await this.updateItemsAndNotifyObservers(currentItems); }; public addItems = async (items: string[]): Promise<void> => { const currentItems = await this.getSetOfCurrentItems(); items.forEach((item) => currentItems.add(item)); log_debug( `addItems: Adding new items: ${items.join( "," )}, current items: ${Array.from(currentItems).join(",")}` ); await this.updateItemsAndNotifyObservers(currentItems); }; public removeItem = async (item: string): Promise<void> => { const currentItems = await this.getSetOfCurrentItems(); currentItems.delete(item); log_debug( `removeItem: Removing item: ${item}, current items: ${Array.from( currentItems ).join(",")}` ); await this.updateItemsAndNotifyObservers(currentItems); }; public removeItems = async (items: string[]): Promise<void> => { const currentItems = await this.getSetOfCurrentItems(); items.forEach((item) => currentItems.delete(item)); log_debug( `removeItems: Removing items: ${items.join( "," )}, current items: ${Array.from(currentItems).join(",")}` ); await this.updateItemsAndNotifyObservers(currentItems); }; public removeAllItems = async (): Promise<void> => { await localStorage.removeItem(this.key, this.namespace); log_debug(`removeAllItems: Removing all items, current items: ${[]}`); this.itemSubject.next([]); }; public getSelectedAsync = async (): Promise<string[]> => { const value = await localStorage.getItem(this.key, this.namespace); const selectedItems = value ? value.split(",") : []; this.itemSubject.next(selectedItems); return selectedItems; }; public getSelectedItems = (): string[] => { return this.itemSubject.getValue(); }; setSelectedItems = async (items: string[]): Promise<void> => { log_debug(`setSelectedItems: Setting selected items: ${items.join(",")}`); await this.updateItemsAndNotifyObservers(new Set(items)); }; }