Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3827a18
Add basic store state for preferences
talldan May 20, 2021
c52bf90
Add more menu component
talldan May 20, 2021
23f7920
Persist preferences
talldan May 20, 2021
f9fb645
Fix translator comment
talldan May 20, 2021
2a3073d
Add a few refinements to the dropdown menu component
talldan May 20, 2021
e19f5e2
Add dropdown menu styles
talldan May 20, 2021
5a27418
Use more menu for edit widgets
talldan May 20, 2021
0b67393
Update edit widgets to use feature toggles
talldan May 20, 2021
8b664e2
Remove some dead code
talldan May 20, 2021
d5497d1
Allow setting default feature values
talldan May 20, 2021
6329f05
Update some newer preferences after rebase
talldan Jul 30, 2021
ed0bba4
Remove invalid tests
talldan Jul 30, 2021
2891d29
Update package.json
talldan Jul 30, 2021
1704f95
Migrate editor preferences to edit-widgets
talldan Aug 5, 2021
b98850a
Update e2e test code for disabling the welcome guide
talldan Aug 5, 2021
6a2e2c7
Move preference defaults to a separate reducer to avoid persistence
talldan Aug 5, 2021
51442e1
Fix - export defaults reducer
talldan Aug 5, 2021
5f4e4c0
Add component docs and missing selector doc
talldan Aug 5, 2021
6d50c38
Add main readme docs
talldan Aug 5, 2021
9dd1b0e
Addthe example to the component docs as well
talldan Aug 5, 2021
a6e40c8
Update changelogs
talldan Aug 5, 2021
fcdbb3d
Add tests for selector
talldan Aug 5, 2021
0fcaf7c
Ensure toggling takes into account the default value
talldan Aug 9, 2021
f44f392
Rename MoreMenuDropdown to OptionsMenuDropdown
talldan Aug 16, 2021
4e6b560
Rename MoreMenuFeatureToggle to OptionsMenuFeatureTogle
talldan Aug 16, 2021
4b48a36
Rename OptionsMenuDropdown to OptionsMenu
talldan Aug 16, 2021
0b2b8c0
Fix style import
talldan Aug 16, 2021
b0f879b
Fix migration handling for multiple stores
talldan Aug 16, 2021
ef7da49
Update docs for migration function
talldan Aug 16, 2021
028565d
Fix store name
talldan Aug 16, 2021
e9c80c4
Revert "Fix style import"
talldan Aug 18, 2021
9931b6d
Revert "Rename OptionsMenuDropdown to OptionsMenu"
talldan Aug 18, 2021
b9e6fd3
Revert "Rename MoreMenuFeatureToggle to OptionsMenuFeatureTogle"
talldan Aug 18, 2021
5067fc2
Revert "Rename MoreMenuDropdown to OptionsMenuDropdown"
talldan Aug 18, 2021
9f58d3a
Remove setFeatureDefaults as an API
talldan Aug 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/data/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

### New Features

- Added a `batch` registry method to batch dispatch calls for performance reasons.
- Added a `batch` registry method to batch dispatch calls for performance reasons.
- Add a new migration for the persistence plugin to migrate edit-widgets preferences to the interface package. As part of this change deprecated migrations for the persistence plugin have been removed ([#33774](https://github.com/WordPress/gutenberg/pull/33774)).

## 6.0.0 (2021-07-29)

Expand Down
113 changes: 51 additions & 62 deletions packages/data/src/plugins/persistence/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { merge, isPlainObject, get, has } from 'lodash';
import { merge, isPlainObject } from 'lodash';

/**
* Internal dependencies
Expand Down Expand Up @@ -223,75 +223,64 @@ function persistencePlugin( registry, pluginOptions ) {
}

/**
* Deprecated: Remove this function and the code in WordPress Core that calls
* it once WordPress 5.4 is released.
* Move the 'features' object in local storage from the sourceStoreName to the
* interface store.
*
* @param {Object} persistence The persistence interface.
* @param {string} sourceStoreName The name of the store that has persisted
* preferences to migrate to the interface
* package.
*/

persistencePlugin.__unstableMigrate = ( pluginOptions ) => {
const persistence = createPersistenceInterface( pluginOptions );

export function migrateFeaturePreferencesToInterfaceStore(
persistence,
sourceStoreName
) {
const interfaceStoreName = 'core/interface';
const state = persistence.get();
const sourcePreferences = state[ sourceStoreName ]?.preferences;
const sourceFeatures = sourcePreferences?.features;

if ( sourceFeatures ) {
const targetFeatures =
state[ interfaceStoreName ]?.preferences?.features;

// Avoid migrating features again if they've previously been migrated.
if ( ! targetFeatures?.[ sourceStoreName ] ) {
// Set the feature values in the interface store, the features
// object is keyed by 'scope', which matches the store name for
// the source.
persistence.set( interfaceStoreName, {
preferences: {
features: {
...targetFeatures,
[ sourceStoreName ]: sourceFeatures,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we at a later stage be consolidating the features that are to be shared across editors (not necessarily all of them) under a "shared" key or something?

Copy link
Contributor Author

@talldan talldan Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This aspect wasn't something I'd considered when working on this task, but it's absolutely possible after this change now that the values are stored in one place.

I think the challenge will be how we reconcile that a user might already have conflicting values for preferences across editors. If I have Top Toolbar active in the post editor, but not active in customize widgets, which one is right?

Other than that, I don't think the implementation of a shared preference would be difficult now, I can think of a few different ways to do it, it all depends on how we'd want it to work. Would it be as simple as one value to rule them all, or might we allow a combination of a global and local preferences?

Some thoughts:

  • It might be that some preferences are singleton, they use a single 'scope' via a shared key
  • It might be that there are still different scopes, but the user is able to change them all to one value in a single action (e.g. a global setting in the WordPress settings menu)
  • It might be that a global setting acts more like a default value, but the user can still override it in an individual editor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all great points.

Regarding global vs local, I was thinking for some options - mostly the a11y/usability related ones, such as text labels on buttons and keeping the cursor inside the block - it make sense to just set them globally, as it's unlikely someone would want to use them in only one editor. For the others, maybe a global option with local override, or local-only makes more sense.

I initially thought of site settings as the best place to put global options, but might be good to get some design input on that too.

},
},
} );

// Migrate 'insertUsage' from 'core/editor' to 'core/block-editor'
const editorInsertUsage = state[ 'core/editor' ]?.preferences?.insertUsage;
if ( editorInsertUsage ) {
const blockEditorInsertUsage =
state[ 'core/block-editor' ]?.preferences?.insertUsage;
persistence.set( 'core/block-editor', {
preferences: {
insertUsage: {
...editorInsertUsage,
...blockEditorInsertUsage,
// Remove feature preferences from the source.
persistence.set( sourceStoreName, {
preferences: {
...sourcePreferences,
features: undefined,
},
},
} );
} );
}
}
}

let editPostState = state[ 'core/edit-post' ];

// Default `fullscreenMode` to `false` if any persisted state had existed
// and the user hadn't made an explicit choice about fullscreen mode. This
// is needed since `fullscreenMode` previously did not have a default value
// and was implicitly false by its absence. It is now `true` by default, but
// this change is not intended to affect upgrades from earlier versions.
const hadPersistedState = Object.keys( state ).length > 0;
const hadFullscreenModePreference = has( state, [
'core/edit-post',
'preferences',
'features',
'fullscreenMode',
] );
if ( hadPersistedState && ! hadFullscreenModePreference ) {
editPostState = merge( {}, editPostState, {
preferences: { features: { fullscreenMode: false } },
} );
}
/**
* Deprecated: Remove this function and the code in WordPress Core that calls
* it once WordPress 6.0 is released.
*/

// Migrate 'areTipsEnabled' from 'core/nux' to 'showWelcomeGuide' in 'core/edit-post'
const areTipsEnabled = get( state, [
'core/nux',
'preferences',
'areTipsEnabled',
] );
const hasWelcomeGuide = has( state, [
'core/edit-post',
'preferences',
'features',
'welcomeGuide',
] );
if ( areTipsEnabled !== undefined && ! hasWelcomeGuide ) {
editPostState = merge( {}, editPostState, {
preferences: {
features: {
welcomeGuide: areTipsEnabled,
},
},
} );
}
persistencePlugin.__unstableMigrate = ( pluginOptions ) => {
const persistence = createPersistenceInterface( pluginOptions );

if ( editPostState !== state[ 'core/edit-post' ] ) {
persistence.set( 'core/edit-post', editPostState );
}
migrateFeaturePreferencesToInterfaceStore(
persistence,
'core/edit-widgets'
);
};

export default persistencePlugin;
118 changes: 117 additions & 1 deletion packages/data/src/plugins/persistence/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import plugin, { createPersistenceInterface, withLazySameState } from '../';
import plugin, {
createPersistenceInterface,
withLazySameState,
migrateFeaturePreferencesToInterfaceStore,
} from '../';
import objectStorage from '../storage/object';
import { createRegistry } from '../../../';

Expand Down Expand Up @@ -377,3 +381,115 @@ describe( 'persistence', () => {
} );
} );
} );

describe( 'migrateFeaturePreferencesToInterfaceStore', () => {
it( 'migrates preferences from the source to the interface store', () => {
const persistenceInterface = createPersistenceInterface( {
storageKey: 'test-username',
} );

const initialState = {
preferences: {
features: {
featureA: true,
featureB: false,
featureC: true,
},
},
};

persistenceInterface.set( 'core/test', initialState );

migrateFeaturePreferencesToInterfaceStore(
persistenceInterface,
'core/test'
);

expect( persistenceInterface.get() ).toEqual( {
'core/interface': {
preferences: {
features: {
'core/test': {
featureA: true,
featureB: false,
featureC: true,
},
},
},
},
'core/test': {
preferences: {
features: undefined,
},
},
} );
} );

it( 'handles multiple preferences from different stores to be migrated', () => {
const persistenceInterface = createPersistenceInterface( {
storageKey: 'test-username',
} );

const initialStateA = {
preferences: {
features: {
featureA: true,
featureB: false,
featureC: true,
},
},
};

const initialStateB = {
preferences: {
features: {
featureD: true,
featureE: false,
featureF: true,
},
},
};

persistenceInterface.set( 'core/test-a', initialStateA );
persistenceInterface.set( 'core/test-b', initialStateB );

migrateFeaturePreferencesToInterfaceStore(
persistenceInterface,
'core/test-a'
);

migrateFeaturePreferencesToInterfaceStore(
persistenceInterface,
'core/test-b'
);

expect( persistenceInterface.get() ).toEqual( {
'core/interface': {
preferences: {
features: {
'core/test-a': {
featureA: true,
featureB: false,
featureC: true,
},
'core/test-b': {
featureD: true,
featureE: false,
featureF: true,
},
},
},
},
'core/test-a': {
preferences: {
features: undefined,
},
},
'core/test-b': {
preferences: {
features: undefined,
},
},
} );
} );
} );
8 changes: 4 additions & 4 deletions packages/e2e-tests/specs/widgets/editing-widgets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ describe( 'Widgets screen', () => {
// Disable welcome guide if it is enabled.
const isWelcomeGuideActive = await page.evaluate( () =>
wp.data
.select( 'core/edit-widgets' )
.__unstableIsFeatureActive( 'welcomeGuide' )
.select( 'core/interface' )
.isFeatureActive( 'core/edit-widgets', 'welcomeGuide' )
);
if ( isWelcomeGuideActive ) {
await page.evaluate( () =>
wp.data
.dispatch( 'core/edit-widgets' )
.__unstableToggleFeature( 'welcomeGuide' )
.dispatch( 'core/interface' )
.toggleFeature( 'core/edit-widgets', 'welcomeGuide' )
);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/edit-widgets/src/components/layout/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ function Interface( { blockEditorSettings } ) {
).getActiveComplementaryArea( editWidgetsStore.name ),
isInserterOpened: !! select( editWidgetsStore ).isInserterOpened(),
hasBlockBreadCrumbsEnabled: select(
editWidgetsStore
).__unstableIsFeatureActive( 'showBlockBreadcrumbs' ),
interfaceStore
).isFeatureActive( 'core/edit-widgets', 'showBlockBreadcrumbs' ),
previousShortcut: select(
keyboardShortcutsStore
).getAllShortcutRawKeyCombinations(
Expand Down
Loading