UNPKG

@itwin/core-frontend

Version:
203 lines • 9.1 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module NativeApp */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Storage = exports.NativeApp = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const FrontendLoggerCategory_1 = require("./common/FrontendLoggerCategory"); const IpcApp_1 = require("./IpcApp"); const NativeAppLogger_1 = require("./NativeAppLogger"); /** NativeApp notifications from backend */ class NativeAppNotifyHandler extends IpcApp_1.NotificationHandler { get channelName() { return core_common_1.nativeAppIpcStrings.notifyChannel; } notifyInternetConnectivityChanged(status) { core_bentley_1.Logger.logInfo(FrontendLoggerCategory_1.FrontendLoggerCategory.NativeApp, "Internet connectivity changed"); NativeApp.onInternetConnectivityChanged.raiseEvent(status); } } /** * The frontend of a native application * @see [Native Applications]($docs/learning/NativeApps.md) * @public */ class NativeApp { static _removeAppNotify; /** A Proxy to call one of the [NativeAppFunctions]($common) functions via IPC. */ static nativeAppIpc = IpcApp_1.IpcApp.makeIpcProxy(core_common_1.nativeAppIpcStrings.channelName); static catalogIpc = IpcApp_1.IpcApp.makeIpcProxy("catalogIModel/ipc"); static _storages = new Map(); static _onOnline = async () => { await NativeApp.setConnectivity(core_common_1.OverriddenBy.Browser, core_common_1.InternetConnectivityStatus.Online); }; static _onOffline = async () => { await NativeApp.setConnectivity(core_common_1.OverriddenBy.Browser, core_common_1.InternetConnectivityStatus.Offline); }; static async setConnectivity(by, status) { await this.nativeAppIpc.overrideInternetConnectivity(by, status); } static hookBrowserConnectivityEvents() { if (typeof window === "object" && window.ononline && window.onoffline) { window.addEventListener("online", this._onOnline); window.addEventListener("offline", this._onOffline); } } static unhookBrowserConnectivityEvents() { if (typeof window === "object" && window.ononline && window.onoffline) { window.removeEventListener("online", this._onOnline); window.removeEventListener("offline", this._onOffline); } } /** event called when internet connectivity changes, if known */ static onInternetConnectivityChanged = new core_bentley_1.BeEvent(); /** determine whether the app currently has internet connectivity, if known */ static async checkInternetConnectivity() { return this.nativeAppIpc.checkInternetConnectivity(); } /** @internal */ static async overrideInternetConnectivity(status) { return this.nativeAppIpc.overrideInternetConnectivity(core_common_1.OverriddenBy.User, status); } static _isValid = false; static get isValid() { return this._isValid; } /** * This is called by either ElectronApp.startup or MobileApp.startup - it should not be called directly * @internal */ static async startup(ipc, opts) { await IpcApp_1.IpcApp.startup(ipc, opts); if (this._isValid) return; this._isValid = true; this._removeAppNotify = NativeAppNotifyHandler.register(); // receives notifications from backend NativeApp.hookBrowserConnectivityEvents(); // initialize current online state. if (window.navigator.onLine) { await this.setConnectivity(core_common_1.OverriddenBy.Browser, window.navigator.onLine ? core_common_1.InternetConnectivityStatus.Online : core_common_1.InternetConnectivityStatus.Offline); } } /** @internal */ static async shutdown() { this._removeAppNotify?.(); NativeApp.unhookBrowserConnectivityEvents(); await NativeAppLogger_1.NativeAppLogger.flush(); await IpcApp_1.IpcApp.shutdown(); this._isValid = false; } static async requestDownloadBriefcase(iTwinId, iModelId, downloadOptions, asOf = core_common_1.IModelVersion.latest()) { const shouldReportProgress = !!downloadOptions.progressCallback; let stopProgressEvents = () => { }; if (shouldReportProgress) { const handleProgress = (_evt, data) => { downloadOptions.progressCallback?.(data); }; stopProgressEvents = IpcApp_1.IpcApp.addListener(`nativeApp.progress-${iModelId}`, handleProgress); } const briefcaseId = (undefined !== downloadOptions.briefcaseId) ? downloadOptions.briefcaseId : (downloadOptions.syncMode === core_common_1.SyncMode.PullOnly ? 0 : await this.nativeAppIpc.acquireNewBriefcaseId(iModelId)); const fileName = downloadOptions.fileName ?? await this.getBriefcaseFileName({ briefcaseId, iModelId }); const requestProps = { iModelId, briefcaseId, iTwinId, asOf: asOf.toJSON(), fileName }; const doDownload = async () => { try { await this.nativeAppIpc.downloadBriefcase(requestProps, shouldReportProgress, downloadOptions.progressInterval); } finally { stopProgressEvents(); } }; const requestCancel = async () => { const status = await this.nativeAppIpc.requestCancelDownloadBriefcase(fileName); if (status) stopProgressEvents(); return status; }; return { briefcaseId, fileName, downloadPromise: doDownload(), requestCancel }; } /** Get the full path filename for a briefcase within the briefcase cache */ static async getBriefcaseFileName(props) { return this.nativeAppIpc.getBriefcaseFileName(props); } /** Delete an existing briefcase * @param fileName the briefcase fileName */ static async deleteBriefcase(fileName) { await this.nativeAppIpc.deleteBriefcaseFiles(fileName); } /** Get a list of all briefcase files held in the local briefcase cache directory */ static async getCachedBriefcases(iModelId) { return this.nativeAppIpc.getCachedBriefcases(iModelId); } /** * Open a [[Storage]]. Creates a new Storage with that name if it does not already exist. * @param name Should be a local filename without an extension. * @returns a Promise for the [[Storage]]. */ static async openStorage(name) { if (this._storages.has(name)) return this._storages.get(name); const storage = new Storage(await this.nativeAppIpc.storageMgrOpen(name)); this._storages.set(storage.id, storage); return storage; } /** * Close a Storage and optionally delete it. * @param storage normally not call directly instead use Storage.close() * @param deleteStorage if true, delete the storage from disk after closing it. */ static async closeStorage(storage, deleteStorage = false) { if (!this._storages.has(storage.id)) throw new Error(`Storage [Id=${storage.id}] not open`); await this.nativeAppIpc.storageMgrClose(storage.id, deleteStorage); this._storages.delete(storage.id); } /** Get the list of existing Storages on the local disk. */ static async getStorageNames() { return NativeApp.nativeAppIpc.storageMgrNames(); } } exports.NativeApp = NativeApp; /** * A local disk-based cache for key value pairs for NativeApps. * @note This should be used only for local caching, since its not guaranteed to exist permanently. * @public */ class Storage { id; constructor(id) { this.id = id; } /** get the type of a value for a key, or undefined if not present. */ async getValueType(key) { return NativeApp.nativeAppIpc.storageGetValueType(this.id, key); } /** Get the value for a key */ async getData(key) { return NativeApp.nativeAppIpc.storageGet(this.id, key); } /** Set value for a key */ async setData(key, value) { return NativeApp.nativeAppIpc.storageSet(this.id, key, value); } /** * Return an array of all keys in this Storage. * @note This can be expensive, depending on the number of keys present. */ async getKeys() { return NativeApp.nativeAppIpc.storageKeys(this.id); } /** Remove a key and its data. */ async removeData(key) { return NativeApp.nativeAppIpc.storageRemove(this.id, key); } /** Remove all keys and their data. */ async removeAll() { return NativeApp.nativeAppIpc.storageRemoveAll(this.id); } } exports.Storage = Storage; //# sourceMappingURL=NativeApp.js.map