Skip to content

Commit

Permalink
Editor: Persist user's 'Show Template' preference (WordPress#69286)
Browse files Browse the repository at this point in the history
* Editor: Persist user's 'Show Template' preference
* Extract logic and finalize
* Simplify the fallback condition
* Restore previous preloading e2e test assertion
* Fix mobile unit tests
* Don't call 'setRenderingMode' while 'defaultMode' is undefined
* Metabox: Check default rendering mode before initialization
* Cleanup selector getters

Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: fabiankaegy <[email protected]>
Co-authored-by: joemcgill <[email protected]>
Co-authored-by: yogeshbhutkar <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: annezazu <[email protected]>
  • Loading branch information
8 people authored Feb 26, 2025
1 parent 7a4b5aa commit c283695
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 54 deletions.
29 changes: 19 additions & 10 deletions packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ function Layout( {
const {
mode,
isFullscreenActive,
hasResolvedMode,
hasActiveMetaboxes,
hasBlockSelected,
showIconLabels,
Expand All @@ -390,7 +391,7 @@ function Layout( {
} = useSelect(
( select ) => {
const { get } = select( preferencesStore );
const { isFeatureActive } = select( editPostStore );
const { isFeatureActive, hasMetaBoxes } = select( editPostStore );
const { canUser, getPostType, getTemplateId } = unlock(
select( coreStore )
);
Expand All @@ -402,22 +403,29 @@ function Layout( {
kind: 'postType',
name: 'wp_template',
} );
const { isZoomOut } = unlock( select( blockEditorStore ) );
const { getEditorMode, getRenderingMode } = select( editorStore );
const { getBlockSelectionStart, isZoomOut } = unlock(
select( blockEditorStore )
);
const { getEditorMode, getRenderingMode, getDefaultRenderingMode } =
unlock( select( editorStore ) );
const isRenderingPostOnly = getRenderingMode() === 'post-only';
const isNotDesignPostType =
! DESIGN_POST_TYPES.includes( currentPostType );
const isDirectlyEditingPattern =
currentPostType === 'wp_block' &&
! onNavigateToPreviousEntityRecord;
const _templateId = getTemplateId( currentPostType, currentPostId );
const defaultMode = getDefaultRenderingMode( currentPostType );

return {
mode: getEditorMode(),
isFullscreenActive:
select( editPostStore ).isFeatureActive( 'fullscreenMode' ),
hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
hasBlockSelected:
!! select( blockEditorStore ).getBlockSelectionStart(),
isFullscreenActive: isFeatureActive( 'fullscreenMode' ),
hasActiveMetaboxes: hasMetaBoxes(),
hasResolvedMode:
defaultMode === 'template-locked'
? !! _templateId
: defaultMode !== undefined,
hasBlockSelected: !! getBlockSelectionStart(),
showIconLabels: get( 'core', 'showIconLabels' ),
isDistractionFree: get( 'core', 'distractionFree' ),
showMetaBoxes:
Expand All @@ -429,7 +437,7 @@ function Layout( {
isViewable &&
canViewTemplate &&
! isEditingTemplate
? getTemplateId( currentPostType, currentPostId )
? _templateId
: null,
enablePaddingAppender:
! isZoomOut() && isRenderingPostOnly && isNotDesignPostType,
Expand All @@ -443,7 +451,8 @@ function Layout( {
onNavigateToPreviousEntityRecord,
]
);
useMetaBoxInitialization( hasActiveMetaboxes );

useMetaBoxInitialization( hasActiveMetaboxes && hasResolvedMode );

const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender(
enablePaddingAppender
Expand Down
14 changes: 8 additions & 6 deletions packages/editor/src/components/post-template/block-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ export default function BlockThemeControl( { id } ) {
id
);
const { createSuccessNotice } = useDispatch( noticesStore );
const { setRenderingMode } = useDispatch( editorStore );
const { setRenderingMode, setDefaultRenderingMode } = unlock(
useDispatch( editorStore )
);

const canCreateTemplate = useSelect(
( select ) =>
Expand Down Expand Up @@ -149,11 +151,11 @@ export default function BlockThemeControl( { id } ) {
isSelected={ ! isTemplateHidden }
role="menuitemcheckbox"
onClick={ () => {
setRenderingMode(
isTemplateHidden
? 'template-locked'
: 'post-only'
);
const newRenderingMode = isTemplateHidden
? 'template-locked'
: 'post-only';
setRenderingMode( newRenderingMode );
setDefaultRenderingMode( newRenderingMode );
} }
>
{ __( 'Show template' ) }
Expand Down
14 changes: 8 additions & 6 deletions packages/editor/src/components/preview-dropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
templateId: getCurrentTemplateId(),
};
}, [] );
const { setDeviceType, setRenderingMode } = useDispatch( editorStore );
const { setDeviceType, setRenderingMode, setDefaultRenderingMode } = unlock(
useDispatch( editorStore )
);
const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) );

const handleDevicePreviewChange = ( newDeviceType ) => {
Expand Down Expand Up @@ -160,11 +162,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
isSelected={ ! isTemplateHidden }
role="menuitemcheckbox"
onClick={ () => {
setRenderingMode(
isTemplateHidden
? 'template-locked'
: 'post-only'
);
const newRenderingMode = isTemplateHidden
? 'template-locked'
: 'post-only';
setRenderingMode( newRenderingMode );
setDefaultRenderingMode( newRenderingMode );
} }
>
{ __( 'Show template' ) }
Expand Down
50 changes: 19 additions & 31 deletions packages/editor/src/components/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ const NON_CONTEXTUAL_POST_TYPES = [
'wp_template_part',
];

/**
* These are rendering modes that the editor supports.
*/
const RENDERING_MODES = [ 'post-only', 'template-locked' ];

/**
* Depending on the post, template and template mode,
* returns the appropriate blocks and change handlers for the block editor provider.
Expand Down Expand Up @@ -183,37 +178,28 @@ export const ExperimentalEditorProvider = withRegistryProvider(
getEditorSelection,
getRenderingMode,
__unstableIsEditorReady,
} = select( editorStore );
const {
getEntitiesConfig,
getPostType,
hasFinishedResolution,
} = select( coreStore );

const postTypeSupports = getPostType( post.type )?.supports;
const hasLoadedPostObject = hasFinishedResolution(
'getPostType',
[ post.type ]
);

const _defaultMode = Array.isArray( postTypeSupports?.editor )
? postTypeSupports.editor.find(
( features ) => 'default-mode' in features
)?.[ 'default-mode' ]
: undefined;
const hasDefaultMode = RENDERING_MODES.includes( _defaultMode );

// Wait for template resolution when rendering in a `template-locked` mode.
getDefaultRenderingMode,
} = unlock( select( editorStore ) );
const { getEntitiesConfig } = select( coreStore );

const _defaultMode = getDefaultRenderingMode( post.type );
/**
* To avoid content "flash", wait until rendering mode has been resolved.
* This is important for the initial render of the editor.
*
* - Wait for template to be resolved if the default mode is 'template-locked'.
* - Wait for default mode to be resolved otherwise.
*/
const hasResolvedMode =
hasLoadedPostObject && _defaultMode === 'template-locked'
_defaultMode === 'template-locked'
? hasTemplate
: true;
: _defaultMode !== undefined;

return {
editorSettings: getEditorSettings(),
isReady: __unstableIsEditorReady() && hasResolvedMode,
mode: getRenderingMode(),
defaultMode: hasDefaultMode ? _defaultMode : 'post-only',
defaultMode: _defaultMode,
selection: getEditorSelection(),
postTypeEntities:
post.type === 'wp_template'
Expand All @@ -224,7 +210,7 @@ export const ExperimentalEditorProvider = withRegistryProvider(
[ post.type, hasTemplate ]
);

const shouldRenderTemplate = !! template && mode !== 'post-only';
const shouldRenderTemplate = hasTemplate && mode !== 'post-only';
const rootLevelPost = shouldRenderTemplate ? template : post;
const defaultBlockContext = useMemo( () => {
const postContext = {};
Expand Down Expand Up @@ -341,7 +327,9 @@ export const ExperimentalEditorProvider = withRegistryProvider(

// Sets the right rendering mode when loading the editor.
useEffect( () => {
setRenderingMode( defaultMode );
if ( defaultMode ) {
setRenderingMode( defaultMode );
}
}, [ defaultMode, setRenderingMode ] );

useHideBlocksFromInserter( post.type, mode );
Expand Down
33 changes: 33 additions & 0 deletions packages/editor/src/store/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,3 +492,36 @@ export const removeTemplates =
.createErrorNotice( errorMessage, { type: 'snackbar' } );
}
};

/**
* Set the default rendering mode preference for the current post type.
*
* @param {string} mode The rendering mode to set as default.
*/
export const setDefaultRenderingMode =
( mode ) =>
( { select, registry } ) => {
const postType = select.getCurrentPostType();
const theme = registry
.select( coreStore )
.getCurrentTheme()?.stylesheet;
const renderingModes =
registry
.select( preferencesStore )
.get( 'core', 'renderingModes' )?.[ theme ] ?? {};

if ( renderingModes[ postType ] === mode ) {
return;
}

const newModes = {
[ theme ]: {
...renderingModes,
[ postType ]: mode,
},
};

registry
.dispatch( preferencesStore )
.set( 'core', 'renderingModes', newModes );
};
57 changes: 57 additions & 0 deletions packages/editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
verse,
} from '@wordpress/icons';
import { store as coreStore } from '@wordpress/core-data';
import { store as preferencesStore } from '@wordpress/preferences';

/**
* Internal dependencies
Expand All @@ -34,6 +35,11 @@ const EMPTY_INSERTION_POINT = {
filterValue: undefined,
};

/**
* These are rendering modes that the editor supports.
*/
const RENDERING_MODES = [ 'post-only', 'template-locked' ];

/**
* Get the inserter.
*
Expand Down Expand Up @@ -215,3 +221,54 @@ export const getPostBlocksByName = createRegistrySelector( ( select ) =>
() => [ select( blockEditorStore ).getBlocks() ]
)
);

/**
* Returns the default rendering mode for a post type by user preference or post type configuration.
*
* @param {Object} state Global application state.
* @param {string} postType The post type.
*
* @return {string} The default rendering mode. Returns `undefined` while resolving value.
*/
export const getDefaultRenderingMode = createRegistrySelector(
( select ) => ( state, postType ) => {
const { getPostType, getCurrentTheme, hasFinishedResolution } =
select( coreStore );

// This needs to be called before `hasFinishedResolution`.
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const currentTheme = getCurrentTheme();
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const postTypeEntity = getPostType( postType );

// Wait for the post type and theme resolution.
if (
! hasFinishedResolution( 'getPostType', [ postType ] ) ||
! hasFinishedResolution( 'getCurrentTheme' )
) {
return undefined;
}

const theme = currentTheme?.stylesheet;
const defaultModePreference = select( preferencesStore ).get(
'core',
'renderingModes'
)?.[ theme ]?.[ postType ];
const postTypeDefaultMode = Array.isArray(
postTypeEntity?.supports?.editor
)
? postTypeEntity.supports.editor.find(
( features ) => 'default-mode' in features
)?.[ 'default-mode' ]
: undefined;

const defaultMode = defaultModePreference || postTypeDefaultMode;

// Fallback gracefully to 'post-only' when rendering mode is not supported.
if ( ! RENDERING_MODES.includes( defaultMode ) ) {
return 'post-only';
}

return defaultMode;
}
);
3 changes: 3 additions & 0 deletions test/e2e/specs/site-editor/preload.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ test.describe( 'Preload', () => {
expect( requests ).toEqual( [
// Seems to be coming from `enableComplementaryArea`.
'/wp/v2/users/me',
// There are two separate settings OPTIONS requests. We should fix
// so the one for canUser and getEntityRecord are reused.
'/wp/v2/settings',
] );
} );
} );
2 changes: 1 addition & 1 deletion test/native/integration-test-helpers/initialize-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function initializeEditor( props, { component } = {} ) {
resolutionSpy.mockImplementation( ( selectorName, args ) => {
// The mobile editor only supports the `post-only` rendering mode, so we
// presume a resolved `getPostType` selector to unblock editor rendering.
if ( 'getPostType' === selectorName ) {
if ( [ 'getPostType', 'getCurrentTheme' ].includes( selectorName ) ) {
return true;
}

Expand Down

0 comments on commit c283695

Please sign in to comment.