Skip to content

Commit 6022b63

Browse files
committed
Update derived block editing modes to support content only template locking
Move contentOnly template locking code from selector to reducer Simplify getBlockEditingMode tests and add additional cases Remove unused dependencies WIP
1 parent b860887 commit 6022b63

File tree

6 files changed

+420
-245
lines changed

6 files changed

+420
-245
lines changed

packages/block-editor/src/store/private-selectors.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ export const getEnabledClientIdsTree = createRegistrySelector( ( select ) =>
115115
state.derivedBlockEditingModes,
116116
state.derivedNavModeBlockEditingModes,
117117
state.blockEditingModes,
118-
state.settings.templateLock,
119-
state.blockListSettings,
120118
select( STORE_NAME ).__unstableGetEditorMode( state ),
121119
] )
122120
);

packages/block-editor/src/store/reducer.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,12 @@ function getDerivedBlockEditingModesForTree(
22672267
syncedPatternClientIds.push( clientId );
22682268
}
22692269
} );
2270+
const contentOnlyTemplateLockedClientIds = Object.keys(
2271+
state.blockListSettings
2272+
).filter(
2273+
( clientId ) =>
2274+
state.blockListSettings[ clientId ]?.templateLock === 'contentOnly'
2275+
);
22702276

22712277
traverseBlockTree( state, treeClientId, ( block ) => {
22722278
const { clientId, name: blockName } = block;
@@ -2457,6 +2463,64 @@ function getDerivedBlockEditingModesForTree(
24572463
derivedBlockEditingModes.set( clientId, 'disabled' );
24582464
}
24592465
}
2466+
2467+
// Explicitly set block editing modes take precedence over template lock.
2468+
if ( state.blockEditingModes.has( clientId ) ) {
2469+
return;
2470+
}
2471+
2472+
if ( contentOnlyTemplateLockedClientIds.length ) {
2473+
const hasContentOnlyTemplateLockedParent =
2474+
!! findParentInClientIdsList(
2475+
state,
2476+
clientId,
2477+
contentOnlyTemplateLockedClientIds
2478+
);
2479+
if ( hasContentOnlyTemplateLockedParent ) {
2480+
if ( isContentBlock( blockName ) ) {
2481+
derivedBlockEditingModes.set( clientId, 'contentOnly' );
2482+
} else {
2483+
derivedBlockEditingModes.set( clientId, 'disabled' );
2484+
}
2485+
}
2486+
}
2487+
2488+
// Disabled block editing modes cascade to all children,
2489+
// but contentOnly can override this, so this is the last
2490+
// thing to check.
2491+
if ( state.blockEditingModes.size ) {
2492+
let parent = state.blocks.parents.get( clientId );
2493+
// Look for the first parent with an explicit block editing mode.
2494+
while ( parent ) {
2495+
const parentBlockEditingMode =
2496+
state.blockEditingModes.get( parent );
2497+
2498+
// If the parent is disabled, this block should be disabled.
2499+
if ( parentBlockEditingMode === 'disabled' ) {
2500+
derivedBlockEditingModes.set( clientId, 'disabled' );
2501+
break;
2502+
}
2503+
2504+
// If the parent is contentOnly, this block should be contentOnly if it's a content block.
2505+
if ( parentBlockEditingMode === 'contentOnly' ) {
2506+
if ( isContentBlock( blockName ) ) {
2507+
derivedBlockEditingModes.set( clientId, 'contentOnly' );
2508+
} else {
2509+
derivedBlockEditingModes.set( clientId, 'disabled' );
2510+
}
2511+
2512+
break;
2513+
}
2514+
2515+
if ( parentBlockEditingMode === 'default' ) {
2516+
// If the parent is default, this block should be default.
2517+
// We can do nothing, but skip searching any further.
2518+
break;
2519+
}
2520+
2521+
parent = state.blocks.parents.get( parent );
2522+
}
2523+
}
24602524
} );
24612525

24622526
return derivedBlockEditingModes;
@@ -2628,6 +2692,75 @@ export function withDerivedBlockEditingModes( reducer ) {
26282692
}
26292693
break;
26302694
}
2695+
case 'UPDATE_BLOCK_LIST_SETTINGS': {
2696+
// Handle the addition and removal of contentOnly template locked blocks.
2697+
const addedBlocks = [];
2698+
const removedClientIds = [];
2699+
2700+
const updates =
2701+
typeof action.clientId === 'string'
2702+
? { [ action.clientId ]: action.settings }
2703+
: action.clientId;
2704+
2705+
for ( const clientId in updates ) {
2706+
const isNewContentOnlyBlock =
2707+
state.blockListSettings[ clientId ]?.templateLock !==
2708+
'contentOnly' &&
2709+
nextState.blockListSettings[ clientId ]
2710+
?.templateLock === 'contentOnly';
2711+
2712+
const wasContentOnlyBlock =
2713+
state.blockListSettings[ clientId ]?.templateLock ===
2714+
'contentOnly' &&
2715+
nextState.blockListSettings[ clientId ]
2716+
?.templateLock !== 'contentOnly';
2717+
2718+
if ( isNewContentOnlyBlock ) {
2719+
addedBlocks.push(
2720+
nextState.blocks.tree.get( clientId )
2721+
);
2722+
} else if ( wasContentOnlyBlock ) {
2723+
removedClientIds.push( clientId );
2724+
}
2725+
}
2726+
2727+
if ( ! addedBlocks.length && ! removedClientIds.length ) {
2728+
break;
2729+
}
2730+
2731+
const nextDerivedBlockEditingModes =
2732+
getDerivedBlockEditingModesUpdates( {
2733+
prevState: state,
2734+
nextState,
2735+
addedBlocks,
2736+
removedClientIds,
2737+
isNavMode: false,
2738+
} );
2739+
const nextDerivedNavModeBlockEditingModes =
2740+
getDerivedBlockEditingModesUpdates( {
2741+
prevState: state,
2742+
nextState,
2743+
addedBlocks,
2744+
removedClientIds,
2745+
isNavMode: true,
2746+
} );
2747+
2748+
if (
2749+
nextDerivedBlockEditingModes ||
2750+
nextDerivedNavModeBlockEditingModes
2751+
) {
2752+
return {
2753+
...nextState,
2754+
derivedBlockEditingModes:
2755+
nextDerivedBlockEditingModes ??
2756+
state.derivedBlockEditingModes,
2757+
derivedNavModeBlockEditingModes:
2758+
nextDerivedNavModeBlockEditingModes ??
2759+
state.derivedNavModeBlockEditingModes,
2760+
};
2761+
}
2762+
break;
2763+
}
26312764
case 'SET_BLOCK_EDITING_MODE':
26322765
case 'UNSET_BLOCK_EDITING_MODE':
26332766
case 'SET_HAS_CONTROLLED_INNER_BLOCKS': {

packages/block-editor/src/store/selectors.js

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3040,62 +3040,36 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) {
30403040
* @return {BlockEditingMode} The block editing mode. One of `'disabled'`,
30413041
* `'contentOnly'`, or `'default'`.
30423042
*/
3043-
export const getBlockEditingMode = createRegistrySelector(
3044-
( select ) =>
3045-
( state, clientId = '' ) => {
3046-
// Some selectors that call this provide `null` as the default
3047-
// rootClientId, but the default rootClientId is actually `''`.
3048-
if ( clientId === null ) {
3049-
clientId = '';
3050-
}
3043+
export function getBlockEditingMode( state, clientId = '' ) {
3044+
// Some selectors that call this provide `null` as the default
3045+
// rootClientId, but the default rootClientId is actually `''`.
3046+
if ( clientId === null ) {
3047+
clientId = '';
3048+
}
30513049

3052-
const isNavMode = isNavigationMode( state );
3053-
3054-
// If the editor is currently not in navigation mode, check if the clientId
3055-
// has an editing mode set in the regular derived map.
3056-
// There may be an editing mode set here for synced patterns or in zoomed out
3057-
// mode.
3058-
if (
3059-
! isNavMode &&
3060-
state.derivedBlockEditingModes?.has( clientId )
3061-
) {
3062-
return state.derivedBlockEditingModes.get( clientId );
3063-
}
3050+
const isNavMode = isNavigationMode( state );
30643051

3065-
// If the editor *is* in navigation mode, the block editing mode states
3066-
// are stored in the derivedNavModeBlockEditingModes map.
3067-
if (
3068-
isNavMode &&
3069-
state.derivedNavModeBlockEditingModes?.has( clientId )
3070-
) {
3071-
return state.derivedNavModeBlockEditingModes.get( clientId );
3072-
}
3052+
// If the editor is currently not in navigation mode, check if the clientId
3053+
// has an editing mode set in the regular derived map.
3054+
// There may be an editing mode set here for synced patterns or in zoomed out
3055+
// mode.
3056+
if ( ! isNavMode && state.derivedBlockEditingModes?.has( clientId ) ) {
3057+
return state.derivedBlockEditingModes.get( clientId );
3058+
}
30733059

3074-
// In normal mode, consider that an explicitly set editing mode takes over.
3075-
const blockEditingMode = state.blockEditingModes.get( clientId );
3076-
if ( blockEditingMode ) {
3077-
return blockEditingMode;
3078-
}
3060+
// If the editor *is* in navigation mode, the block editing mode states
3061+
// are stored in the derivedNavModeBlockEditingModes map.
3062+
if ( isNavMode && state.derivedNavModeBlockEditingModes?.has( clientId ) ) {
3063+
return state.derivedNavModeBlockEditingModes.get( clientId );
3064+
}
30793065

3080-
// In normal mode, top level is default mode.
3081-
if ( clientId === '' ) {
3082-
return 'default';
3083-
}
3066+
// In normal mode, consider that an explicitly set editing mode takes over.
3067+
if ( state.blockEditingModes.has( clientId ) ) {
3068+
return state.blockEditingModes.get( clientId );
3069+
}
30843070

3085-
const rootClientId = getBlockRootClientId( state, clientId );
3086-
const templateLock = getTemplateLock( state, rootClientId );
3087-
// If the parent of the block is contentOnly locked, check whether it's a content block.
3088-
if ( templateLock === 'contentOnly' ) {
3089-
const name = getBlockName( state, clientId );
3090-
const { hasContentRoleAttribute } = unlock(
3091-
select( blocksStore )
3092-
);
3093-
const isContent = hasContentRoleAttribute( name );
3094-
return isContent ? 'contentOnly' : 'disabled';
3095-
}
3096-
return 'default';
3097-
}
3098-
);
3071+
return 'default';
3072+
}
30993073

31003074
/**
31013075
* Indicates if a block is ungroupable.

packages/block-editor/src/store/test/private-selectors.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,10 @@ describe( 'private selectors', () => {
504504
[ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', 'disabled' ],
505505
[ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', 'disabled' ],
506506
] ),
507+
derivedBlockEditingModes: new Map( [
508+
[ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', 'disabled' ],
509+
[ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', 'disabled' ],
510+
] ),
507511
blockListSettings: {},
508512
};
509513
expect(

0 commit comments

Comments
 (0)