import { setStorage , getStorage } from './storage' ; import { Bridge } from './bridge' ; import { isMac } from './env' ; const internalSharedData = { openInEditorHost : '/' , componentNameStyle : 'class' , theme : 'auto' , displayDensity : 'low' , timeFormat : 'default' , recordVuex : true , cacheVuexSnapshotsEvery : 50 , cacheVuexSnapshotsLimit : 10 , snapshotLoading : false , componentEventsEnabled : true , performanceMonitoringEnabled : true , editableProps : false , logDetected : true , vuexNewBackend : false , vuexAutoload : false , vuexGroupGettersByModule : true , showMenuScrollTip : true , timelineTimeGrid : true , timelineScreenshots : true , menuStepScrolling : isMac , pluginPermissions : { } as any , pluginSettings : { } as any , pageConfig : { } as any , debugInfo : false , } ; const persisted = [ 'componentNameStyle' , 'theme' , 'displayDensity' , 'recordVuex' , 'editableProps' , 'logDetected' , 'vuexNewBackend' , 'vuexAutoload' , 'vuexGroupGettersByModule' , 'timeFormat' , 'showMenuScrollTip' , 'timelineTimeGrid' , 'timelineScreenshots' , 'menuStepScrolling' , 'pluginPermissions' , 'pluginSettings' , 'performanceMonitoringEnabled' , 'componentEventsEnabled' , 'debugInfo' , ] ; const storageVersion = '6.0.0-alpha.1' ; let bridge ; let persist = false ; let data ; let initRetryInterval ; let initRetryCount = 0 ; export interface SharedDataParams { bridge : Bridge ; persist : boolean ; Vue ? : any ; } const initCbs = [ ] ; export function initSharedData ( params ) { return new Promise ( ( resolve ) => { bridge = params . bridge ; persist = ! ! params . persist ; if ( persist ) { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Master init in progress...' ) ; } persisted . forEach ( key => { const value = getStorage ( `vue-devtools-${ storageVersion }:shared-data:${ key }` ) ; if ( value !== null ) { internalSharedData [ key ] = value ; } } ) ; bridge . on ( 'shared-data:load' , ( ) => { Object . keys ( internalSharedData ) . forEach ( key => { sendValue ( key , internalSharedData [ key ] ) ; } ) ; bridge . send ( 'shared-data:load-complete' ) ; } ) ; bridge . on ( 'shared-data:init-complete' , ( ) => { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Master init complete' ) ; } clearInterval ( initRetryInterval ) ; resolve ( ) ; } ) ; bridge . send ( 'shared-data:master-init-waiting' ) ; bridge . on ( 'shared-data:minion-init-waiting' , ( ) => { bridge . send ( 'shared-data:master-init-waiting' ) ; } ) ; initRetryCount = 0 ; clearInterval ( initRetryInterval ) ; initRetryInterval = setInterval ( ( ) => { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Master init retrying...' ) ; } bridge . send ( 'shared-data:master-init-waiting' ) ; initRetryCount ++ ; if ( initRetryCount > 30 ) { clearInterval ( initRetryInterval ) ; console . error ( '[shared data] Master init failed' ) ; } } , 2000 ) ; } else { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Minion init in progress...' ) ; } bridge . on ( 'shared-data:master-init-waiting' , ( ) => { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Minion loading data...' ) ; } bridge . send ( 'shared-data:load' ) ; bridge . once ( 'shared-data:load-complete' , ( ) => { if ( process . env . NODE_ENV !== 'production' ) { console . log ( '[shared data] Minion init complete' ) ; } bridge . send ( 'shared-data:init-complete' ) ; resolve ( ) ; } ) ; } ) ; bridge . send ( 'shared-data:minion-init-waiting' ) ; } data = { ... internalSharedData , } ; if ( params . Vue ) { data = params . Vue . observable ( data ) ; } bridge . on ( 'shared-data:set' , ( { key , value } ) => { setValue ( key , value ) ; } ) ; initCbs . forEach ( cb => cb ( ) ) ; } ) ; } export function onSharedDataInit ( cb ) { initCbs . push ( cb ) ; return ( ) => { const index = initCbs . indexOf ( cb ) ; if ( index !== - 1 ) initCbs . splice ( index , 1 ) ; } ; } export function destroySharedData ( ) { bridge . removeAllListeners ( 'shared-data:set' ) ; watchers = { } ; } let watchers = { } ; function setValue ( key , value ) { if ( persist && persisted . includes ( key ) ) { setStorage ( `vue-devtools-${ storageVersion }:shared-data:${ key }` , value ) ; } const oldValue = data [ key ] ; data [ key ] = value ; const handlers = watchers [ key ] ; if ( handlers ) { handlers . forEach ( h => h ( value , oldValue ) ) ; } return true ; } function sendValue ( key , value ) { bridge && bridge . send ( 'shared-data:set' , { key , value , } ) ; } export function watchSharedData ( prop , handler ) { const list = watchers [ prop ] || ( watchers [ prop ] = [ ] ) ; list . push ( handler ) ; return ( ) => { const index = list . indexOf ( handler ) ; if ( index !== - 1 ) list . splice ( index , 1 ) ; } ; } const proxy = { } ; Object . keys ( internalSharedData ) . forEach ( key => { Object . defineProperty ( proxy , key , { configurable : false , get : ( ) => data [ key ] , set : ( value ) => { sendValue ( key , value ) ; setValue ( key , value ) ; } , } ) ; } ) ; export const SharedData = proxy ;