@itwin/core-frontend
Version:
iTwin.js frontend components
203 lines • 9.1 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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
;