Add method to clear persistent storage (#142)

This commit is contained in:
Don McCurdy 2023-03-08 03:19:27 -08:00 committed by GitHub
parent c75f998174
commit 1bb80991c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 5 deletions

View file

@ -28,6 +28,8 @@ import {getAllPossibleAssetIDs} from '@theatre/shared/utils/assets'
import {notify} from './notify' import {notify} from './notify'
import type {RafDriverPrivateAPI} from '@theatre/core/rafDrivers' import type {RafDriverPrivateAPI} from '@theatre/core/rafDrivers'
const DEFAULT_PERSISTENCE_KEY = 'theatre-0.4'
export type CoreExports = typeof _coreExports export type CoreExports = typeof _coreExports
const UIConstructorModule = const UIConstructorModule =
@ -159,7 +161,7 @@ export class Studio {
} }
const storeOpts: Parameters<typeof this._store['initialize']>[0] = { const storeOpts: Parameters<typeof this._store['initialize']>[0] = {
persistenceKey: 'theatre-0.4', persistenceKey: DEFAULT_PERSISTENCE_KEY,
usePersistentStorage: true, usePersistentStorage: true,
} }
@ -515,4 +517,8 @@ export class Studio {
}, },
} }
} }
clearPersistentStorage(persistenceKey = DEFAULT_PERSISTENCE_KEY) {
this._store.__experimental_clearPersistentStorage(persistenceKey)
}
} }

View file

@ -20,7 +20,10 @@ import type {Atom, Pointer} from '@theatre/dataverse'
import type {Draft} from 'immer' import type {Draft} from 'immer'
import {createDraft, finishDraft} from 'immer' import {createDraft, finishDraft} from 'immer'
import type {Store} from 'redux' import type {Store} from 'redux'
import {persistStateOfStudio} from './persistStateOfStudio' import {
__experimental_clearPersistentStorage,
persistStateOfStudio,
} from './persistStateOfStudio'
import type {OnDiskState} from '@theatre/core/projects/store/storeTypes' import type {OnDiskState} from '@theatre/core/projects/store/storeTypes'
import {generateDiskStateRevision} from './generateDiskStateRevision' import {generateDiskStateRevision} from './generateDiskStateRevision'
@ -89,6 +92,13 @@ export default class StudioStore {
return this._reduxStore.getState() return this._reduxStore.getState()
} }
__experimental_clearPersistentStorage(
persistenceKey: string,
): FullStudioState {
__experimental_clearPersistentStorage(this._reduxStore, persistenceKey)
return this.getState()
}
/** /**
* This method causes the store to start the history from scratch. This is useful * This method causes the store to start the history from scratch. This is useful
* for testing and development where you want to explicitly provide a state to the * for testing and development where you want to explicitly provide a state to the

View file

@ -5,6 +5,11 @@ import type {FullStudioState} from '@theatre/studio/store/index'
import debounce from 'lodash-es/debounce' import debounce from 'lodash-es/debounce'
import type {Store} from 'redux' import type {Store} from 'redux'
const lastStateByStore = new WeakMap<
Store<FullStudioState>,
StudioPersistentState
>()
export const persistStateOfStudio = ( export const persistStateOfStudio = (
reduxStore: Store<FullStudioState>, reduxStore: Store<FullStudioState>,
onInitialize: () => void, onInitialize: () => void,
@ -14,16 +19,16 @@ export const persistStateOfStudio = (
reduxStore.dispatch(studioActions.replacePersistentState(s)) reduxStore.dispatch(studioActions.replacePersistentState(s))
} }
const storageKey = localStoragePrefix + '.persistent' const storageKey = getStorageKey(localStoragePrefix)
const getState = () => reduxStore.getState().$persistent const getState = () => reduxStore.getState().$persistent
loadFromPersistentStorage() loadFromPersistentStorage()
let lastState = getState()
const persist = () => { const persist = () => {
const newState = getState() const newState = getState()
const lastState = lastStateByStore.get(reduxStore)
if (newState === lastState) return if (newState === lastState) return
lastState = newState lastStateByStore.set(reduxStore, newState)
localStorage.setItem(storageKey, JSON.stringify(newState)) localStorage.setItem(storageKey, JSON.stringify(newState))
} }
reduxStore.subscribe(debounce(persist, 1000)) reduxStore.subscribe(debounce(persist, 1000))
@ -54,3 +59,22 @@ export const persistStateOfStudio = (
} }
} }
} }
export const __experimental_clearPersistentStorage = (
reduxStore: Store<FullStudioState>,
localStoragePrefix: string,
) => {
// This removes the persisted state from localStorage,
// while also preventing the current state from being persisted on window unload.
// Once the new storage PR lands, this method won't be needed anymore.
const storageKey = getStorageKey(localStoragePrefix)
const currentState = reduxStore.getState().$persistent
localStorage.removeItem(storageKey)
// prevent the current state from being persistent on window unload,
// unless further state changes are made.
lastStateByStore.set(reduxStore, currentState)
}
function getStorageKey(localStoragePrefix: string) {
return localStoragePrefix + '.persistent'
}

View file

@ -409,6 +409,14 @@ export interface IStudio {
* Disables the play/pause keyboard shortcut (spacebar) * Disables the play/pause keyboard shortcut (spacebar)
*/ */
__experimental_enablePlayPauseKeyboardShortcut(): void __experimental_enablePlayPauseKeyboardShortcut(): void
/**
* Clears persistent storage and ensures that the current state will not be
* saved on window unload. Further changes to state will continue writing to
* persistent storage, if enabled during initialization.
*
* @param persistenceKey - same persistencyKey as in `studio.initialize(opts)`, if any
*/
__experimental_clearPersistentStorage(persistenceKey?: string): void
} }
} }
@ -446,6 +454,9 @@ export default class TheatreStudio implements IStudio {
// see __experimental_disblePlayPauseKeyboardShortcut() // see __experimental_disblePlayPauseKeyboardShortcut()
__experimental_enablePlayPauseKeyboardShortcut() __experimental_enablePlayPauseKeyboardShortcut()
}, },
__experimental_clearPersistentStorage(persistenceKey?: string): void {
return getStudio().clearPersistentStorage(persistenceKey)
},
} }
/** /**