diff --git a/client/gutenberg/editor/calypso-store/actions.js b/client/gutenberg/editor/calypso-store/actions.js new file mode 100644 index 000000000000..b8f64153d19c --- /dev/null +++ b/client/gutenberg/editor/calypso-store/actions.js @@ -0,0 +1,4 @@ +export const setSelectedSiteId = selectedSiteId => ( { + type: 'GUTENLYPSO_SELECTED_SITE_ID_SET', + selectedSiteId, +} ); diff --git a/client/gutenberg/editor/calypso-store/index.js b/client/gutenberg/editor/calypso-store/index.js new file mode 100644 index 000000000000..c30039758e3c --- /dev/null +++ b/client/gutenberg/editor/calypso-store/index.js @@ -0,0 +1,19 @@ +/** + * WordPress Dependencies + */ +import { registerStore } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import reducer from './reducer'; +import * as actions from './actions'; +import * as selectors from './selectors'; + +const store = registerStore( 'gutenberg/calypso', { + reducer, + actions, + selectors, +} ); + +export default store; diff --git a/client/gutenberg/editor/calypso-store/reducer.js b/client/gutenberg/editor/calypso-store/reducer.js new file mode 100644 index 000000000000..877266bd5264 --- /dev/null +++ b/client/gutenberg/editor/calypso-store/reducer.js @@ -0,0 +1,10 @@ +/* eslint-disable wpcalypso/import-docblock */ +/** + * WordPress dependencies + */ +import { combineReducers } from '@wordpress/data'; + +const selectedSiteId = ( state = null, action ) => + 'GUTENLYPSO_SELECTED_SITE_ID_SET' === action.type ? action.selectedSiteId : state; + +export default combineReducers( { selectedSiteId } ); diff --git a/client/gutenberg/editor/calypso-store/selectors.js b/client/gutenberg/editor/calypso-store/selectors.js new file mode 100644 index 000000000000..34bd270208c2 --- /dev/null +++ b/client/gutenberg/editor/calypso-store/selectors.js @@ -0,0 +1 @@ +export const getSelectedSiteId = state => state.selectedSiteId; diff --git a/client/gutenberg/editor/controller.js b/client/gutenberg/editor/controller.js index 755402a27610..f871a69bce88 100644 --- a/client/gutenberg/editor/controller.js +++ b/client/gutenberg/editor/controller.js @@ -12,7 +12,7 @@ import { has, set, uniqueId } from 'lodash'; * WordPress dependencies */ import { setLocaleData } from '@wordpress/i18n'; -import { dispatch } from '@wordpress/data'; +import { dispatch, select } from '@wordpress/data'; /** * Internal dependencies @@ -110,6 +110,22 @@ export const loadGutenbergBlockAvailability = store => { } ); }; +export const resetGutenbergState = ( registry, selectedSiteId ) => { + // Always reset core/editor, core/notices, and other UI parts + registry.reset( 'core/editor' ); + registry.reset( 'core/notices' ); + dispatch( 'core/edit-post' ).closePublishSidebar(); + dispatch( 'core/edit-post' ).closeModal(); + + // Only reset core/data on site change + const previousGutenbergSiteId = select( 'gutenberg/calypso' ).getSelectedSiteId(); + + if ( !! previousGutenbergSiteId && previousGutenbergSiteId !== selectedSiteId ) { + registry.resetCoreResolvers(); + } + dispatch( 'gutenberg/calypso' ).setSelectedSiteId( selectedSiteId ); +}; + export const redirect = ( { store: { getState } }, next ) => { const state = getState(); const siteId = getSelectedSiteId( state ); @@ -140,10 +156,7 @@ export const post = async ( context, next ) => { const { Editor, registry } = initGutenberg( userId, context.store ); - // Reset the Gutenberg state - registry.reset(); - dispatch( 'core/edit-post' ).closePublishSidebar(); - dispatch( 'core/edit-post' ).closeModal(); + resetGutenbergState( registry, siteId ); return props => ( diff --git a/client/gutenberg/editor/init.js b/client/gutenberg/editor/init.js index 34e46fc4e642..d90acd3b559a 100644 --- a/client/gutenberg/editor/init.js +++ b/client/gutenberg/editor/init.js @@ -34,26 +34,34 @@ const addResetToRegistry = registry => { window.gutenbergState = () => mapValues( registry.stores, ( { store } ) => store.getState() ); } - const resettableStores = [ 'core/editor', 'core/notices' ]; - const stores = []; return { registerStore( namespace, options ) { - let store; - if ( -1 === resettableStores.indexOf( namespace ) ) { - store = registry.registerStore( namespace, options ); - } else { - store = registry.registerStore( namespace, { - ...options, - reducer: ( state, action ) => - options.reducer( 'GUTENLYPSO_RESET' === action.type ? undefined : state, action ), - } ); - } + const store = registry.registerStore( namespace, { + ...options, + reducer: ( state, action ) => { + if ( 'GUTENLYPSO_RESET' === action.type && namespace === action.namespace ) { + debug( `Resetting ${ namespace } store` ); + return options.reducer( undefined, action ); + } + return options.reducer( state, action ); + }, + } ); stores.push( store ); return store; }, - reset() { - stores.forEach( store => store.dispatch( { type: 'GUTENLYPSO_RESET' } ) ); + reset( namespace ) { + stores.forEach( store => store.dispatch( { type: 'GUTENLYPSO_RESET', namespace } ) ); + }, + resetCoreResolvers() { + // @see https://github.com/WordPress/gutenberg/blob/e1092c0d0b75fe53ab57bc6c4cc9e32cb2e74e40/packages/data/src/resolvers-cache-middleware.js#L14-L34 + const resolvers = registry.select( 'core/data' ).getCachedResolvers( 'core' ); + debug( `Resetting core store resolvers: ${ Object.keys( resolvers ).toString() }` ); + Object.entries( resolvers ).forEach( ( [ selectorName, resolversByArgs ] ) => { + resolversByArgs.forEach( ( value, args ) => { + registry.dispatch( 'core/data' ).invalidateResolution( 'core', selectorName, args ); + } ); + } ); }, }; }; @@ -63,12 +71,15 @@ const addResetToRegistry = registry => { export const initGutenberg = once( ( userId, store ) => { debug( 'Starting Gutenberg editor initialization...' ); + const registry = use( addResetToRegistry ); + debug( 'Registering data plugins' ); const storageKey = 'WP_DATA_USER_' + userId; use( plugins.persistence, { storageKey: storageKey } ); use( plugins.controls ); - const registry = use( addResetToRegistry ); + debug( 'Initializing gutenberg/calypso store' ); + require( 'gutenberg/editor/calypso-store' ); // We need to ensure that core-data is loaded after the data plugins have been registered. debug( 'Initializing core-data store' );