Skip to content

Commit

Permalink
Calculate both the regular and nav mode derived block editing modes a…
Browse files Browse the repository at this point in the history
…t the same time
  • Loading branch information
talldan committed Nov 25, 2024
1 parent f849f5b commit 7b25f6e
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 53 deletions.
4 changes: 1 addition & 3 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1669,16 +1669,14 @@ export const setNavigationMode =
*/
export const __unstableSetEditorMode =
( mode ) =>
( { registry, dispatch } ) => {
( { registry } ) => {
registry.dispatch( preferencesStore ).set( 'core', 'editorTool', mode );

if ( mode === 'navigation' ) {
speak( __( 'You are currently in Write mode.' ) );
} else if ( mode === 'edit' ) {
speak( __( 'You are currently in Design mode.' ) );
}

dispatch( { type: 'SET_EDITOR_MODE', mode } );
};

/**
Expand Down
200 changes: 161 additions & 39 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
store as blocksStore,
privateApis as blocksPrivateApis,
} from '@wordpress/blocks';
import { store as preferencesStore } from '@wordpress/preferences';

/**
* Internal dependencies
Expand Down Expand Up @@ -2241,17 +2240,18 @@ function hasBindings( block ) {
* This function calculates the editing modes for each block in the tree, taking into account
* various factors such as zoom level, navigation mode, sections, and synced patterns.
*
* @param {Object} state The current state object.
* @param {string} treeClientId The client ID of the root block for the tree. Defaults to an empty string.
*
* @param {Object} state The current state object.
* @param {boolean} isNavMode Whether the navigation mode is active.
* @param {string} treeClientId The client ID of the root block for the tree. Defaults to an empty string.
* @return {Map} A Map containing the derived block editing modes, keyed by block client ID.
*/
function getDerivedBlockEditingModesForTree( state, treeClientId = '' ) {
function getDerivedBlockEditingModesForTree(
state,
isNavMode = false,
treeClientId = ''
) {
const isZoomedOut =
state?.zoomLevel < 100 || state?.zoomLevel === 'auto-scaled';
const isNavMode =
select( preferencesStore )?.get( 'core', 'editorTool' ) ===
'navigation';
const derivedBlockEditingModes = new Map();

// When there are sections, the majority of blocks are disabled,
Expand Down Expand Up @@ -2402,21 +2402,24 @@ function getDerivedBlockEditingModesForTree( state, treeClientId = '' ) {
*
* It only returns a value when modifications are made to the block editing modes.
*
* @param {Object} options The options for updating derived block editing modes.
* @param {Object} options.prevState The previous state object.
* @param {Object} options.nextState The next state object.
* @param {Array} [options.addedBlocks] An array of blocks that were added.
* @param {Array} [options.removedClientIds] An array of client IDs of blocks that were removed.
*
* @param {Object} options The options for updating derived block editing modes.
* @param {Object} options.prevState The previous state object.
* @param {Object} options.nextState The next state object.
* @param {Array} [options.addedBlocks] An array of blocks that were added.
* @param {Array} [options.removedClientIds] An array of client IDs of blocks that were removed.
* @param {boolean} [options.isNavMode] Whether the navigation mode is active.
* @return {Map|undefined} The updated derived block editing modes, or undefined if no changes were made.
*/
function getDerivedBlockEditingModesUpdates( {
prevState,
nextState,
addedBlocks,
removedClientIds,
isNavMode = false,
} ) {
const prevDerivedBlockEditingModes = prevState.derivedBlockEditingModes;
const prevDerivedBlockEditingModes = isNavMode
? prevState.derivedNavModeBlockEditingModes
: prevState.derivedBlockEditingModes;
let nextDerivedBlockEditingModes;

// Perform removals before additions to handle cases like the `MOVE_BLOCKS_TO_POSITION` action.
Expand All @@ -2442,6 +2445,7 @@ function getDerivedBlockEditingModesUpdates( {
traverseBlockTree( nextState, addedBlock.clientId, ( block ) => {
const updates = getDerivedBlockEditingModesForTree(
nextState,
isNavMode,
block.clientId
);

Expand Down Expand Up @@ -2497,12 +2501,28 @@ export function withDerivedBlockEditingModes( reducer ) {
prevState: state,
nextState,
removedClientIds: action.clientIds,
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
removedClientIds: action.clientIds,
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
Expand All @@ -2514,12 +2534,28 @@ export function withDerivedBlockEditingModes( reducer ) {
prevState: state,
nextState,
addedBlocks: action.blocks,
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: action.blocks,
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
Expand All @@ -2532,17 +2568,34 @@ export function withDerivedBlockEditingModes( reducer ) {
if ( ! updatedBlock ) {
break;
}

const nextDerivedBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: [ updatedBlock ],
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: [ updatedBlock ],
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
Expand All @@ -2554,54 +2607,105 @@ export function withDerivedBlockEditingModes( reducer ) {
nextState,
addedBlocks: action.blocks,
removedClientIds: action.clientIds,
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds: action.clientIds,
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
}
case 'REPLACE_INNER_BLOCKS': {
// Get the clientIds of the blocks that are being replaced
// from the old state, before they were removed.
const removedClientIds = state.blocks.order.get(
action.rootClientId
);
const nextDerivedBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: action.blocks,
// Get the clientIds of the blocks that are being replaced
// from the old state, before they were removed.
removedClientIds: state.blocks.order.get(
action.rootClientId
),
removedClientIds,
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds,
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
}
case 'MOVE_BLOCKS_TO_POSITION': {
const addedBlocks = action.clientIds.map( ( clientId ) => {
return nextState.blocks.byClientId.get( clientId );
} );
const nextDerivedBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks: action.clientIds.map( ( clientId ) => {
return nextState.blocks.byClientId.get( clientId );
} ),
// Get the clientIds of the blocks that are being replaced
// from the old state, before they were removed.
addedBlocks,
removedClientIds: action.clientIds,
isNavMode: false,
} );
const nextDerivedNavModeBlockEditingModes =
getDerivedBlockEditingModesUpdates( {
prevState: state,
nextState,
addedBlocks,
removedClientIds: action.clientIds,
isNavMode: true,
} );

if ( nextDerivedBlockEditingModes ) {
if (
nextDerivedBlockEditingModes ||
nextDerivedNavModeBlockEditingModes
) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes,
derivedBlockEditingModes:
nextDerivedBlockEditingModes ??
state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes:
nextDerivedNavModeBlockEditingModes ??
state.derivedNavModeBlockEditingModes,
};
}
break;
Expand All @@ -2615,7 +2719,15 @@ export function withDerivedBlockEditingModes( reducer ) {
return {
...nextState,
derivedBlockEditingModes:
getDerivedBlockEditingModesForTree( nextState ),
getDerivedBlockEditingModesForTree(
nextState,
false /* Nav mode off */
),
derivedNavModeBlockEditingModes:
getDerivedBlockEditingModesForTree(
nextState,
true /* Nav mode on */
),
};
}
break;
Expand All @@ -2629,7 +2741,15 @@ export function withDerivedBlockEditingModes( reducer ) {
return {
...nextState,
derivedBlockEditingModes:
getDerivedBlockEditingModesForTree( nextState ),
getDerivedBlockEditingModesForTree(
nextState,
false /* Nav mode off */
),
derivedNavModeBlockEditingModes:
getDerivedBlockEditingModesForTree(
nextState,
true /* Nav mode on */
),
};
}
}
Expand All @@ -2638,6 +2758,8 @@ export function withDerivedBlockEditingModes( reducer ) {
// state need to be preserved.
nextState.derivedBlockEditingModes =
state?.derivedBlockEditingModes ?? new Map();
nextState.derivedNavModeBlockEditingModes =
state?.derivedNavModeBlockEditingModes ?? new Map();

return nextState;
};
Expand Down
22 changes: 21 additions & 1 deletion packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3041,10 +3041,30 @@ export const getBlockEditingMode = createRegistrySelector(
clientId = '';
}

if ( state.derivedBlockEditingModes?.has( clientId ) ) {
const isNavMode =
select( preferencesStore )?.get( 'core', 'editorTool' ) ===
'navigation';

// If the editor is currently not in navigation mode, check if the clientId
// has an editing mode set in the regular derived map.
// There may be an editing mode set here for synced patterns or in zoomed out
// mode.
if (
! isNavMode &&
state.derivedBlockEditingModes?.has( clientId )
) {
return state.derivedBlockEditingModes.get( clientId );
}

// If the editor *is* in navigation mode, the block editing mode states
// are stored in the derivedNavModeBlockEditingModes map.
if (
isNavMode &&
state.derivedNavModeBlockEditingModes?.has( clientId )
) {
return state.derivedNavModeBlockEditingModes.get( clientId );
}

// In normal mode, consider that an explicitely set editing mode takes over.
const blockEditingMode = state.blockEditingModes.get( clientId );
if ( blockEditingMode ) {
Expand Down
Loading

0 comments on commit 7b25f6e

Please sign in to comment.