diff --git a/theatre/shared/src/globals.ts b/theatre/shared/src/globals.ts index fde07f6..cbeb706 100644 --- a/theatre/shared/src/globals.ts +++ b/theatre/shared/src/globals.ts @@ -1,6 +1,5 @@ const globals = { - disableStatePersistence: false, - currentProjectStateDefinitionVersion: '0.3.0-dev', + currentProjectStateDefinitionVersion: '0.4.0', } export default globals diff --git a/theatre/shared/src/setupTestEnv.ts b/theatre/shared/src/setupTestEnv.ts index 5f8b0af..336ce12 100644 --- a/theatre/shared/src/setupTestEnv.ts +++ b/theatre/shared/src/setupTestEnv.ts @@ -1,3 +1 @@ -import globals from './globals' - -globals.disableStatePersistence = true +export {} diff --git a/theatre/shared/src/testUtils.ts b/theatre/shared/src/testUtils.ts index f2c477c..e6ce59e 100644 --- a/theatre/shared/src/testUtils.ts +++ b/theatre/shared/src/testUtils.ts @@ -12,6 +12,9 @@ import globals from './globals' let lastProjectN = 0 export async function setupTestSheet(sheetState: SheetState_Historic) { + const studio = getStudio()! + studio.initialize({usePersistentStorage: false}) + const projectState: ProjectState_Historic = { definitionVersion: globals.currentProjectStateDefinitionVersion, sheetsById: { @@ -41,8 +44,6 @@ export async function setupTestSheet(sheetState: SheetState_Historic) { const obj = privateAPI(objPublicAPI) - const studio = getStudio()! - return { obj, objPublicAPI, diff --git a/theatre/studio/src/Studio.ts b/theatre/studio/src/Studio.ts index 6a347cf..8a3e959 100644 --- a/theatre/studio/src/Studio.ts +++ b/theatre/studio/src/Studio.ts @@ -18,6 +18,8 @@ import type {IProject, ISheet} from '@theatre/core' import PaneManager from './PaneManager' import type * as _coreExports from '@theatre/core/coreExports' import type {OnDiskState} from '@theatre/core/projects/store/storeTypes' +import type {Deferred} from '@theatre/shared/utils/defer' +import {defer} from '@theatre/shared/utils/defer' export type CoreExports = typeof _coreExports @@ -38,6 +40,8 @@ export class Studio { readonly paneManager: PaneManager private _coreAtom = new Atom<{core?: CoreExports}>({}) + private readonly _initializedDeferred: Deferred = defer() + private _initializeFnCalled = false get atomP() { return this._store.atomP @@ -55,8 +59,39 @@ export class Studio { this.paneManager = new PaneManager(this) } - get initialized() { - return this._store.initialized + async initialize(opts?: Parameters[0]) { + if (this._initializeFnCalled) { + return this._initializedDeferred.promise + } + const storeOpts: Parameters[0] = { + persistenceKey: 'theatre-0.4', + usePersistentStorage: true, + } + + if (typeof opts?.persistenceKey === 'string') { + storeOpts.persistenceKey = opts.persistenceKey + } + + if (opts?.usePersistentStorage === false) { + storeOpts.usePersistentStorage = false + } + + try { + await this._store.initialize(storeOpts) + } catch (e) { + this._initializedDeferred.reject(e) + return + } + + this._initializedDeferred.resolve() + + if (process.env.NODE_ENV !== 'test') { + this.ui.render() + } + } + + get initialized(): Promise { + return this._initializedDeferred.promise } _attachToIncomingProjects() { diff --git a/theatre/studio/src/StudioStore/StudioStore.ts b/theatre/studio/src/StudioStore/StudioStore.ts index 4db8424..d22c570 100644 --- a/theatre/studio/src/StudioStore/StudioStore.ts +++ b/theatre/studio/src/StudioStore/StudioStore.ts @@ -11,6 +11,7 @@ import type { StudioEphemeralState, StudioHistoricState, } from '@theatre/studio/store/types' +import type {Deferred} from '@theatre/shared/utils/defer' import {defer} from '@theatre/shared/utils/defer' import forEachDeep from '@theatre/shared/utils/forEachDeep' import getDeep from '@theatre/shared/utils/getDeep' @@ -26,7 +27,6 @@ import get from 'lodash-es/get' import type {Store} from 'redux' import {persistStateOfStudio} from './persistStateOfStudio' import {isSheetObject} from '@theatre/shared/instanceTypes' -import globals from '@theatre/shared/globals' import type {OnDiskState} from '@theatre/core/projects/store/storeTypes' import {generateDiskStateRevision} from './generateDiskStateRevision' @@ -52,7 +52,6 @@ export default class StudioStore { private readonly _reduxStore: Store private readonly _atom: Atom readonly atomP: Pointer - readonly initialized: Promise constructor() { this._reduxStore = configureStore({ @@ -61,23 +60,32 @@ export default class StudioStore { }) this._atom = atomFromReduxStore(this._reduxStore) this.atomP = this._atom.pointer + } - if (globals.disableStatePersistence !== true) { - const d = defer() - this.initialized = d.promise - persistStateOfStudio(this._reduxStore, () => { - this.tempTransaction(({drafts}) => { - drafts.ephemeral.initialised = true - }).commit() - d.resolve() - }) + initialize(opts: { + persistenceKey: string + usePersistentStorage: boolean + }): Promise { + const d: Deferred = defer() + if (opts.usePersistentStorage === true) { + persistStateOfStudio( + this._reduxStore, + () => { + this.tempTransaction(({drafts}) => { + drafts.ephemeral.initialised = true + }).commit() + d.resolve() + }, + opts.persistenceKey, + ) } else { this.tempTransaction(({drafts}) => { drafts.ephemeral.initialised = true }).commit() - this.initialized = Promise.resolve() + d.resolve() } + return d.promise } getState(): FullStudioState { diff --git a/theatre/studio/src/StudioStore/persistStateOfStudio.ts b/theatre/studio/src/StudioStore/persistStateOfStudio.ts index 0b291a5..06c430a 100644 --- a/theatre/studio/src/StudioStore/persistStateOfStudio.ts +++ b/theatre/studio/src/StudioStore/persistStateOfStudio.ts @@ -5,17 +5,16 @@ import type {FullStudioState} from '@theatre/studio/store/index' import debounce from 'lodash-es/debounce' import type {Store} from 'redux' -const studioPersistenceKey = 'theatrejs:0.3/studio' - export const persistStateOfStudio = ( reduxStore: Store, onInitialize: () => void, + localStoragePrefix: string, ) => { const loadState = (s: StudioPersistentState) => { reduxStore.dispatch(studioActions.replacePersistentState(s)) } - const storageKey = studioPersistenceKey + '.persistent' + const storageKey = localStoragePrefix + '.persistent' const getState = () => reduxStore.getState().$persistent loadFromPersistentStorage() diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index 1955de1..69dff6a 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -104,7 +104,21 @@ export interface IStudio { * Initializes the studio. Call it once in your index.js/index.ts module. * It silently ignores subsequent calls. */ - initialize(): void + initialize(opts?: { + /** + * The local storage key to use to persist the state. + * + * @default "theatrejs:0.4" + */ + persistenceKey?: string + /** + * Whether to persist the changes in the browser's temporary storage. + * It is useful to set this to false in the test environment or when debugging things. + * + * @default true + */ + usePersistentStorage?: boolean + }): void transaction(fn: (api: ITransactionAPI) => void): void scrub(): IScrub @@ -189,8 +203,9 @@ export default class TheatreStudio implements IStudio { */ constructor(internals: Studio) {} - initialize() { - getStudio().ui.render() + initialize(opts?: Parameters[0]): Promise { + const studio = getStudio() + return studio.initialize(opts) } extend(extension: IExtension): void { diff --git a/tsconfig.base.json b/tsconfig.base.json index a7fec57..1a0f4b2 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -14,7 +14,6 @@ "skipDefaultLibCheck": true, "declarationMap": true, "stripInternal": true, - // "emitDeclarationOnly": true, "declaration": true, "paths": { "@theatre/core": ["./theatre/core/src/index.ts"],