Skip to content

Commit

Permalink
Avoid persisting preference every time the sidebar tab is changed (#4…
Browse files Browse the repository at this point in the history
…0923)

* Turn complementary areas into a standard action/selector/reducer, unhooking it from the preferences store

* Handle visibility in selectors, and resolve issues with actions and reducer

* Update test description

* My site editor general sidebar active by default

* Revert "My site editor general sidebar active by default"

This reverts commit 334734c.

* Preserve site editor behavior as best as possible by denoting a default area

* Use an explicit action when setting up the site editor app to denote the default action

* Migrate any stored data

* Remove DISABLE_COMPLEMENTARY_AREA handling in interface reducer
  • Loading branch information
talldan authored May 13, 2022
1 parent 3383af2 commit 27ec8f6
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 13 deletions.
2 changes: 2 additions & 0 deletions packages/edit-site/src/components/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function SidebarComplementaryAreaFills() {
[]
);
const { enableComplementaryArea } = useDispatch( interfaceStore );

useEffect( () => {
if ( ! isEditorSidebarOpened ) return;
if ( hasBlockSelection ) {
Expand All @@ -54,6 +55,7 @@ export function SidebarComplementaryAreaFills() {
enableComplementaryArea( STORE_NAME, SIDEBAR_TEMPLATE );
}
}, [ hasBlockSelection, isEditorSidebarOpened ] );

let sidebarName = sidebar;
if ( ! isEditorSidebarOpened ) {
sidebarName = hasBlockSelection ? SIDEBAR_BLOCK : SIDEBAR_TEMPLATE;
Expand Down
6 changes: 6 additions & 0 deletions packages/edit-site/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
__experimentalFetchUrlData as fetchUrlData,
} from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
import { store as interfaceStore } from '@wordpress/interface';
import { store as preferencesStore } from '@wordpress/preferences';
import { __ } from '@wordpress/i18n';
import { store as viewportStore } from '@wordpress/viewport';
Expand Down Expand Up @@ -77,6 +78,11 @@ export function reinitializeEditor( target, settings ) {
dispatch( editSiteStore ).setIsListViewOpened( true );
}

dispatch( interfaceStore ).setDefaultComplementaryArea(
'core/edit-site',
'edit-site/template'
);

dispatch( editSiteStore ).updateSettings( settings );

// Keep the defaultTemplateTypes in the core/editor settings too,
Expand Down
49 changes: 42 additions & 7 deletions packages/interface/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,50 @@
import deprecated from '@wordpress/deprecated';
import { store as preferencesStore } from '@wordpress/preferences';

/**
* Set a default complementary area.
*
* @param {string} scope Complementary area scope.
* @param {string} area Area identifier.
*
* @return {Object} Action object.
*/
export const setDefaultComplementaryArea = ( scope, area ) => ( {
type: 'SET_DEFAULT_COMPLEMENTARY_AREA',
scope,
area,
} );

/**
* Enable the complementary area.
*
* @param {string} scope Complementary area scope.
* @param {string} area Area identifier.
*/
export const enableComplementaryArea = ( scope, area ) => ( { registry } ) => {
export const enableComplementaryArea = ( scope, area ) => ( {
registry,
dispatch,
} ) => {
// Return early if there's no area.
if ( ! area ) {
return;
}

registry
.dispatch( preferencesStore )
.set( scope, 'complementaryArea', area );
const isComplementaryAreaVisible = registry
.select( preferencesStore )
.get( scope, 'isComplementaryAreaVisible' );

if ( ! isComplementaryAreaVisible ) {
registry
.dispatch( preferencesStore )
.set( scope, 'isComplementaryAreaVisible', true );
}

dispatch( {
type: 'ENABLE_COMPLEMENTARY_AREA',
scope,
area,
} );
};

/**
Expand All @@ -27,9 +56,15 @@ export const enableComplementaryArea = ( scope, area ) => ( { registry } ) => {
* @param {string} scope Complementary area scope.
*/
export const disableComplementaryArea = ( scope ) => ( { registry } ) => {
registry
.dispatch( preferencesStore )
.set( scope, 'complementaryArea', null );
const isComplementaryAreaVisible = registry
.select( preferencesStore )
.get( scope, 'isComplementaryAreaVisible' );

if ( isComplementaryAreaVisible ) {
registry
.dispatch( preferencesStore )
.set( scope, 'isComplementaryAreaVisible', false );
}
};

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/interface/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createReduxStore, register } from '@wordpress/data';
*/
import * as actions from './actions';
import * as selectors from './selectors';
import reducer from './reducer';
import { STORE_NAME } from './constants';

/**
Expand All @@ -18,7 +19,7 @@ import { STORE_NAME } from './constants';
* @type {Object}
*/
export const store = createReduxStore( STORE_NAME, {
reducer: () => {},
reducer,
actions,
selectors,
} );
Expand Down
35 changes: 35 additions & 0 deletions packages/interface/src/store/reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* WordPress dependencies
*/
import { combineReducers } from '@wordpress/data';

export function complementaryAreas( state = {}, action ) {
switch ( action.type ) {
case 'SET_DEFAULT_COMPLEMENTARY_AREA': {
const { scope, area } = action;

// If there's already an area, don't overwrite it.
if ( state[ scope ] ) {
return state;
}

return {
...state,
[ scope ]: area,
};
}
case 'ENABLE_COMPLEMENTARY_AREA': {
const { scope, area } = action;
return {
...state,
[ scope ]: area,
};
}
}

return state;
}

export default combineReducers( {
complementaryAreas,
} );
21 changes: 19 additions & 2 deletions packages/interface/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,28 @@ import { store as preferencesStore } from '@wordpress/preferences';
* @param {Object} state Global application state.
* @param {string} scope Item scope.
*
* @return {string} The complementary area that is active in the given scope.
* @return {string | null | undefined} The complementary area that is active in the given scope.
*/
export const getActiveComplementaryArea = createRegistrySelector(
( select ) => ( state, scope ) => {
return select( preferencesStore ).get( scope, 'complementaryArea' );
const isComplementaryAreaVisible = select( preferencesStore ).get(
scope,
'isComplementaryAreaVisible'
);

// Return `undefined` to indicate that the user has never toggled
// visibility, this is the vanilla default. Other code relies on this
// nuance in the return value.
if ( isComplementaryAreaVisible === undefined ) {
return undefined;
}

// Return `null` to indicate the user hid the complementary area.
if ( ! isComplementaryAreaVisible ) {
return null;
}

return state?.complementaryAreas?.[ scope ];
}
);

Expand Down
2 changes: 1 addition & 1 deletion packages/interface/src/store/test/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe( 'actions', () => {
} );

describe( 'disableComplementaryArea', () => {
it( 'removes any assignment to a complementary area', () => {
it( 'results in the complementary area being inactive', () => {
registry
.dispatch( interfaceStore )
.enableComplementaryArea( 'my-plugin', 'custom-sidebar' );
Expand Down
5 changes: 3 additions & 2 deletions packages/preferences-persistence/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import create from './create';
import convertLegacyLocalStorageData from './migrations/legacy-local-storage-data';
import convertPreferencesPackageData from './migrations/preferences-package-data';

export { create };

Expand Down Expand Up @@ -34,9 +35,9 @@ export function __unstableCreatePersistenceLayer( serverData, userId ) {

let preloadedData;
if ( serverData && serverModified >= localModified ) {
preloadedData = serverData;
preloadedData = convertPreferencesPackageData( serverData );
} else if ( localData ) {
preloadedData = localData;
preloadedData = convertPreferencesPackageData( localData );
} else {
// Check if there is data in the legacy format from the old persistence system.
preloadedData = convertLegacyLocalStorageData( userId );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default function convertComplementaryAreas( state ) {
return Object.keys( state ).reduce( ( stateAccumulator, scope ) => {
const scopeData = state[ scope ];

// If a complementary area is truthy, convert it to the `isComplementaryAreaVisible` boolean.
if ( scopeData?.complementaryArea ) {
const updatedScopeData = { ...scopeData };
delete updatedScopeData.complementaryArea;
updatedScopeData.isComplementaryAreaVisible = true;
stateAccumulator[ scope ] = updatedScopeData;
return stateAccumulator;
}

return stateAccumulator;
}, state );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Internal dependencies
*/
import convertComplementaryAreas from './convert-complementary-areas';

export default function convertPreferencesPackageData( data ) {
return convertComplementaryAreas( data );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Internal dependencies
*/
import convertComplementaryAreas from '../convert-complementary-areas';

describe( 'convertComplementaryAreas', () => {
it( 'converts the `complementaryArea` property in each scope to an `isComplementaryAreaVisible` boolean', () => {
const input = {
'core/customize-widgets': {
complementaryArea: 'edit-post/block',
},
'core/edit-site': {
complementaryArea: 'edit-site/template',
},
'core/edit-post': {
complementaryArea: 'edit-post/block',
},
'core/edit-widgets': {},
};

const expectedOutput = {
'core/customize-widgets': {
isComplementaryAreaVisible: true,
},
'core/edit-site': {
isComplementaryAreaVisible: true,
},
'core/edit-post': {
isComplementaryAreaVisible: true,
},
'core/edit-widgets': {},
};

expect( convertComplementaryAreas( input ) ).toEqual( expectedOutput );
} );
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Internal dependencies
*/
import convertPreferencesPackageData from '../';

const input = {
'core/customize-widgets': {
welcomeGuide: false,
fixedToolbar: true,
},
'core/edit-widgets': {
welcomeGuide: false,
fixedToolbar: true,
showBlockBreadcrumbs: false,
complementaryArea: 'edit-widgets/block-areas',
},
'core/edit-post': {
welcomeGuide: false,
fixedToolbar: true,
fullscreenMode: false,
hiddenBlockTypes: [ 'core/audio', 'core/cover' ],
editorMode: 'visual',
preferredStyleVariations: {
'core/quote': 'large',
},
inactivePanels: [],
openPanels: [ 'post-status' ],
pinnedItems: {
'my-sidebar-plugin/title-sidebar': false,
},
},
'core/edit-site': {
welcomeGuide: false,
welcomeGuideStyles: false,
fixedToolbar: true,
complementaryArea: 'edit-site/global-styles',
},
};

describe( 'convertPreferencesPackageData', () => {
it( 'converts data to the expected format', () => {
expect( convertPreferencesPackageData( input ) )
.toMatchInlineSnapshot( `
Object {
"core/customize-widgets": Object {
"fixedToolbar": true,
"welcomeGuide": false,
},
"core/edit-post": Object {
"editorMode": "visual",
"fixedToolbar": true,
"fullscreenMode": false,
"hiddenBlockTypes": Array [
"core/audio",
"core/cover",
],
"inactivePanels": Array [],
"openPanels": Array [
"post-status",
],
"pinnedItems": Object {
"my-sidebar-plugin/title-sidebar": false,
},
"preferredStyleVariations": Object {
"core/quote": "large",
},
"welcomeGuide": false,
},
"core/edit-site": Object {
"fixedToolbar": true,
"isComplementaryAreaVisible": true,
"welcomeGuide": false,
"welcomeGuideStyles": false,
},
"core/edit-widgets": Object {
"fixedToolbar": true,
"isComplementaryAreaVisible": true,
"showBlockBreadcrumbs": false,
"welcomeGuide": false,
},
}
` );
} );
} );

0 comments on commit 27ec8f6

Please sign in to comment.