UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

193 lines (143 loc) • 5.81 kB
import { bridgeLogger } from "../../zapp-react-native-bridge/logger"; import { BehaviorSubject } from "rxjs"; import { Storage } from "@applicaster/zapp-react-native-bridge/ZappStorage/Storage"; import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage"; import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage"; import { StorageType } from "../appUtils/contextKeysManager/consts"; import { getNamespaceAndKey } from "../appUtils/contextKeysManager/utils"; import { createLogger } from "../logger"; 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< StorageType, Record<string, StorageMultiSelectProvider> > = { [StorageType.local]: {}, [StorageType.session]: {}, // TODO: not implemented yet [StorageType.secure]: {}, }; public static getProvider( keyNamespace: string, storage: StorageType = StorageType.local ): MultiSelectProvider { if (!this.multiSelectProviders[storage][keyNamespace]) { const storageImpl = storage === StorageType.session ? sessionStorage : localStorage; this.multiSelectProviders[storage][keyNamespace] = new StorageMultiSelectProvider(keyNamespace, storageImpl); } return this.multiSelectProviders[storage][keyNamespace]; } private itemSubject: BehaviorSubject<string[] | null>; private readonly key: string; private readonly namespace: string; private constructor( keyNamespace: string, private storage: Storage ) { const { namespace, key } = getNamespaceAndKey(keyNamespace); if (!key) { throw new Error("StorageMultiSelectProvider: Key is required"); } this.key = key; this.namespace = namespace; this.storage.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 this.storage.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 this.storage.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 this.storage.removeItem(this.key, this.namespace); log_debug(`removeAllItems: Removing all items, current items: ${[]}`); this.itemSubject.next([]); }; public getSelectedAsync = async (): Promise<string[]> => { const value = await this.storage.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)); }; }