import { flatten } from 'lodash' import { makeObservable, observable } from 'mobx'; import { DehydratedElement, ElementDataWrapper, ElementSchemaVersion, OfflineStatus, } from '../interfaces' import { MainStore } from './mainStore' export class OfflineStore { main: MainStore offlineStatus?: OfflineStatus = undefined constructor(main: MainStore) { makeObservable(this, { offlineStatus: observable, }) this.main = main } async initializeStorage() { return this.main?.offlineService?.initializeStorage() } async getElementsList(): Promise { return this.main.offlineService?.getElementsList() || [] } async getLocalElementsList(): Promise { return this.main.offlineService?.getLocalElementsList() || [] } async saveElement(hash: string, element: DehydratedElement) { return this.main.offlineService?.saveElement(hash, element) } getElement(hash: string): DehydratedElement | null { return this.main.offlineService?.getElement(hash) || null } async removeElement(hash: string) { return this.main.offlineService?.removeElement(hash) } async saveListing(hash: string, data: ElementDataWrapper[]) { return this.main.offlineService?.saveListing(hash, data) } async getListing(hash: string): Promise { return this.main.offlineService?.getListing(hash) || [] } async clearElementsAndListing() { await this.main.offlineService?.clearElementsAndListing() } async preloadOfflineMetadata() { try { // Element metadata this.offlineStatus = { currentStep: 'Downloading metadata', } await this.preloadElementMetadata() // Organization specific offline data await this.main.userStore.organizationConfig.app?.offline?.setupOfflineResources?.( this.main, (message) => { this.offlineStatus ? (this.offlineStatus.currentStep = message) : null }, ) } catch (e) { if (e instanceof Error) { this.offlineStatus = { lastError: e.toString(), } } return } this.offlineStatus = { completedAt: new Date().toISOString(), } } async preloadElementMetadata() { const config = this.main.userStore.organizationConfig?.app?.offline const organization = this.main.userStore.organization.id if (!config) { return } const promises = config.preloadTypes.map((model) => { const schemaPromises = this.main.userStore.schemaVersion === ElementSchemaVersion.V1 ? [ this.main.elementStore.getElementTemplateV1( model.TYPE, organization, ), this.main.elementStore.getElementTypeData(model.TYPE), ] : [ this.main.elementStore.getTemplate(model.TYPE), this.main.elementStore.getElementSchema(model.TYPE), ] return [ this.main.elementStore.getElementPrivileges(model.TYPE, organization), ...schemaPromises, ] }) await Promise.all(flatten(promises)) } async loadOfflineStatus() { const offlineKey = this.getOfflineKey() this.offlineStatus = await this.main.offlineService?.getItem(offlineKey) } persistOfflineStatus() { const offlineKey = this.getOfflineKey() return this.main.offlineService?.setItem(offlineKey, this.offlineStatus) } async clearOfflineStatus() { const offlineKey = this.getOfflineKey() await this.main.offlineService?.removeItem?.(offlineKey) await this.loadOfflineStatus() } getOfflineKey() { return `offline_data/${this.main.userStore.organization.id}` } }