forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstorage.js
More file actions
1 lines (1 loc) · 5.42 KB
/
storage.js
File metadata and controls
1 lines (1 loc) · 5.42 KB
1
import{set,entries,createStore}from"./thirdparty/idb-keyval.js";!function setupGlobalStorage(){if(window.PhStore)return void console.error("window.PhStore already setup. Ignoring.");const EVENT_CHANGED="change",FIRST_BOOT_TIME="firstBootTime";let storageNodeConnector,_testKey,nodeStoragePhoenixApis={};const isBrowser=!Phoenix.isNativeApp,isDesktop=Phoenix.isNativeApp,PHSTORE_DB="PhStore",PHSTORE_STORE_NAME="KVStore";let idbStore;function _getIDBStorage(){return idbStore||(idbStore=createStore(PHSTORE_DB,PHSTORE_STORE_NAME)),idbStore}const PHOENIX_STORAGE_BROADCAST_CHANNEL_NAME="ph-storage",EXTERNAL_CHANGE_BROADCAST_INTERVAL=500,CHANGE_TYPE_EXTERNAL="External",CHANGE_TYPE_INTERNAL="Internal",MGS_CHANGE="change";let cache={},pendingBroadcastKV={},watchExternalKeys={};function commitExternalChanges(changedKV){for(let key of Object.keys(changedKV))if(watchExternalKeys[key]){const externalChange=changedKV[key];(!cache[key]||externalChange.t>cache[key].t)&&(cache[key]=externalChange,PhStore.trigger(key,CHANGE_TYPE_EXTERNAL))}}if(isDesktop){const STORAGE_NODE_CONNECTOR_ID="ph_storage";storageNodeConnector=window.PhNodeEngine.createNodeConnector(STORAGE_NODE_CONNECTOR_ID,nodeStoragePhoenixApis),window._tauriBootVarsPromise.then(()=>{storageNodeConnector.execPeer("openDB",window._tauriBootVars.appLocalDir)}),Phoenix.isTestWindow&&(window.storageNodeConnector=storageNodeConnector),storageNodeConnector.on("change",(_evt,changedKV)=>{commitExternalChanges(changedKV)})}if(isBrowser){const storageChannel=new BroadcastChannel("ph-storage");setInterval(()=>{storageChannel.postMessage({type:"change",keys:pendingBroadcastKV}),pendingBroadcastKV={}},500),storageChannel.onmessage=(event=>{const message=event.data;"change"===message.type&&commitExternalChanges(message.keys)})}function getItem(key){let cachedResult=cache[key];return cachedResult&&cachedResult.v?JSON.parse(cachedResult.v):null}const MINUTES_10=1e4;let errorCountReported=0,sendOnceMore=!1,noFurtherReporting=!1;function _reportPutItemError(err){window.debugMode&&console.error(err);const logger=window.logger;logger&&!noFurtherReporting&&(errorCountReported++,sendOnceMore&&(noFurtherReporting=!0,logger.reportError(err,`${errorCountReported} tauri:storage:setItem failures in ${MINUTES_10/1e3} minutes`)),1===errorCountReported&&(logger.reportError(err),setTimeout(()=>{sendOnceMore=!0},MINUTES_10)))}function setItem(key,value){const valueToStore={t:Date.now(),v:JSON.stringify(value)};Phoenix.isTestWindow&&key!==_testKey||(isDesktop&&(storageNodeConnector.execPeer("putItem",{key:key,value:valueToStore}).catch(_reportPutItemError),window.__TAURI__?window.__TAURI__.invoke("put_item",{key:key,value:JSON.stringify(valueToStore)}):window.__ELECTRON__&&window.electronAPI.putItem(key,JSON.stringify(valueToStore))),(window.debugMode||isBrowser)&&set(key,valueToStore,_getIDBStorage())),cache[key]=valueToStore,watchExternalKeys[key]&&isBrowser&&(pendingBroadcastKV[key]=valueToStore),PhStore.trigger(key,CHANGE_TYPE_INTERNAL)}function removeItem(key){setItem(key,null)}function watchExternalChanges(key){if(watchExternalKeys[key]=!0,isDesktop&&(!Phoenix.isTestWindow||key===_testKey)){const t=cache[key]&&cache[key].t||0;storageNodeConnector.execPeer("watchExternalChanges",{key:key,t:t})}}function unwatchExternalChanges(key){delete watchExternalKeys[key],!isDesktop||Phoenix.isTestWindow&&key!==_testKey||storageNodeConnector.execPeer("unwatchExternalChanges",key)}function setupFirstBoot(){try{const firstBootTime=getItem(FIRST_BOOT_TIME);firstBootTime||(window.Phoenix.firstBoot=!0,setItem(FIRST_BOOT_TIME,Date.now()));let legacyKey="healthData.firstUseDay";localStorage.getItem(legacyKey)&&(window.Phoenix.firstBoot=!1)}catch(e){console.error(e)}}const storageReadyPromise=new Promise(resolve=>{if(Phoenix.isTestWindow)resolve();else if(isDesktop){async function mergeNativeInMemoryStorage(){try{let map={};window.__TAURI__?map=await window.__TAURI__.invoke("get_all_items")||{}:window.__ELECTRON__&&(map=await window.electronAPI.getAllItems()||{});for(const key of Object.keys(map))cache[key]=JSON.parse(map[key])}catch(e){console.error(e)}setupFirstBoot(),resolve()}window._tauriStorageRestorePromise.then(jsonData=>{jsonData&&(cache=JSON.parse(jsonData))}).catch(console.error).finally(mergeNativeInMemoryStorage)}else entries(_getIDBStorage()).then(kvArrayAll=>{for(let kvArray of kvArrayAll)cache[kvArray[0]]=kvArray[1]}).catch(console.error).finally(()=>{setupFirstBoot(),resolve()})}),_PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY="desktopZoomScale";async function flushDB(){isDesktop&&await storageNodeConnector.execPeer("flushDB")}async function persistDBForReboot(){isDesktop&&await storageNodeConnector.execPeer("dumpDBToFile")}storageReadyPromise.then(()=>{const zoomFactor=PhStore.getItem("desktopZoomScale")||1;window.__TAURI__?window.__TAURI__.tauri.invoke("zoom_window",{scaleFactor:zoomFactor}):window.__ELECTRON__&&window.electronAPI.zoomWindow(zoomFactor)});const PhStore={getItem:getItem,setItem:setItem,removeItem:removeItem,flushDB:flushDB,persistDBForReboot:persistDBForReboot,watchExternalChanges:watchExternalChanges,unwatchExternalChanges:unwatchExternalChanges,storageReadyPromise:storageReadyPromise,_storageBootstrapTime:Date.now()-Phoenix.startTime,_PHSTORE_BOOT_DESKTOP_ZOOM_SCALE_KEY:"desktopZoomScale",CHANGE_TYPE_INTERNAL:CHANGE_TYPE_INTERNAL,CHANGE_TYPE_EXTERNAL:CHANGE_TYPE_EXTERNAL};Phoenix.isTestWindow&&(PhStore._setTestKey=function(testKey){_testKey=testKey}),EventDispatcher.makeEventDispatcher(PhStore),window.PhStore=PhStore}();