Skip to content

Commit

Permalink
Use a context provider for global styles config (#35622)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad authored Oct 14, 2021
1 parent b371822 commit 5572d59
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 234 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { store as editSiteStore } from '../../store';
*/
import { useGlobalStylesOutput } from '../global-styles/use-global-styles-output';

export function useGlobalStylesRenderer() {
function useGlobalStylesRenderer() {
const [ styles, settings ] = useGlobalStylesOutput();
const { getSettings } = useSelect( editSiteStore );
const { updateSettings } = useDispatch( editSiteStore );
Expand All @@ -35,3 +35,9 @@ export function useGlobalStylesRenderer() {
} );
}, [ styles, settings ] );
}

export function GlobalStylesRenderer() {
useGlobalStylesRenderer();

return null;
}
170 changes: 88 additions & 82 deletions packages/edit-site/src/components/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ import InserterSidebar from '../secondary-sidebar/inserter-sidebar';
import ListViewSidebar from '../secondary-sidebar/list-view-sidebar';
import ErrorBoundary from '../error-boundary';
import { store as editSiteStore } from '../../store';
import { useGlobalStylesRenderer } from './global-styles-renderer';
import { GlobalStylesRenderer } from './global-styles-renderer';
import { GlobalStylesProvider } from '../global-styles/global-styles-provider';

const interfaceLabels = {
secondarySidebar: __( 'Block Library' ),
Expand Down Expand Up @@ -159,8 +160,6 @@ function Editor( { initialSettings, onError } ) {
}
}, [ isNavigationOpen ] );

useGlobalStylesRenderer();

// Don't render the Editor until the settings are set and loaded
if ( ! settings?.siteUrl ) {
return null;
Expand All @@ -186,87 +185,94 @@ function Editor( { initialSettings, onError } ) {
type={ templateType }
id={ entityId }
>
<BlockContextProvider value={ blockContext }>
<ErrorBoundary onError={ onError }>
<FullscreenMode isActive />
<UnsavedChangesWarning />
<KeyboardShortcuts.Register />
<SidebarComplementaryAreaFills />
<InterfaceSkeleton
labels={ interfaceLabels }
drawer={ <NavigationSidebar /> }
secondarySidebar={ secondarySidebar() }
sidebar={
sidebarIsOpened && (
<ComplementaryArea.Slot scope="core/edit-site" />
)
}
header={
<Header
openEntitiesSavedStates={
openEntitiesSavedStates
}
/>
}
notices={ <EditorSnackbars /> }
content={
<>
<EditorNotices />
{ template && (
<BlockEditor
setIsInserterOpen={
setIsInserterOpened
}
/>
) }
{ templateResolved &&
! template &&
settings?.siteUrl &&
entityId && (
<Notice
status="warning"
isDismissible={ false }
>
{ __(
"You attempted to edit an item that doesn't exist. Perhaps it was deleted?"
) }
</Notice>
<GlobalStylesProvider>
<BlockContextProvider value={ blockContext }>
<GlobalStylesRenderer />
<ErrorBoundary onError={ onError }>
<FullscreenMode isActive />
<UnsavedChangesWarning />
<KeyboardShortcuts.Register />
<SidebarComplementaryAreaFills />
<InterfaceSkeleton
labels={ interfaceLabels }
drawer={ <NavigationSidebar /> }
secondarySidebar={ secondarySidebar() }
sidebar={
sidebarIsOpened && (
<ComplementaryArea.Slot scope="core/edit-site" />
)
}
header={
<Header
openEntitiesSavedStates={
openEntitiesSavedStates
}
/>
}
notices={ <EditorSnackbars /> }
content={
<>
<EditorNotices />
{ template && (
<BlockEditor
setIsInserterOpen={
setIsInserterOpened
}
/>
) }
<KeyboardShortcuts />
</>
}
actions={
<>
{ isEntitiesSavedStatesOpen ? (
<EntitiesSavedStates
close={
closeEntitiesSavedStates
}
/>
) : (
<div className="edit-site-editor__toggle-save-panel">
<Button
variant="secondary"
className="edit-site-editor__toggle-save-panel-button"
onClick={
openEntitiesSavedStates
{ templateResolved &&
! template &&
settings?.siteUrl &&
entityId && (
<Notice
status="warning"
isDismissible={
false
}
>
{ __(
"You attempted to edit an item that doesn't exist. Perhaps it was deleted?"
) }
</Notice>
) }
<KeyboardShortcuts />
</>
}
actions={
<>
{ isEntitiesSavedStatesOpen ? (
<EntitiesSavedStates
close={
closeEntitiesSavedStates
}
aria-expanded={ false }
>
{ __(
'Open save panel'
) }
</Button>
</div>
) }
</>
}
footer={ <BlockBreadcrumb /> }
/>
<Popover.Slot />
<PluginArea />
</ErrorBoundary>
</BlockContextProvider>
/>
) : (
<div className="edit-site-editor__toggle-save-panel">
<Button
variant="secondary"
className="edit-site-editor__toggle-save-panel-button"
onClick={
openEntitiesSavedStates
}
aria-expanded={
false
}
>
{ __(
'Open save panel'
) }
</Button>
</div>
) }
</>
}
footer={ <BlockBreadcrumb /> }
/>
<Popover.Slot />
<PluginArea />
</ErrorBoundary>
</BlockContextProvider>
</GlobalStylesProvider>
</EntityProvider>
</EntityProvider>
</SlotFillProvider>
Expand Down
15 changes: 15 additions & 0 deletions packages/edit-site/src/components/global-styles/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* WordPress dependencies
*/
import { createContext } from '@wordpress/element';

export const DEFAULT_GLOBAL_STYLES_CONTEXT = {
user: {},
base: {},
merged: {},
setUserConfig: () => {},
};

export const GlobalStylesContext = createContext(
DEFAULT_GLOBAL_STYLES_CONTEXT
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* External dependencies
*/
import { get, cloneDeep, set, mergeWith } from 'lodash';

/**
* WordPress dependencies
*/
import { useMemo, useCallback } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';
import { PRESET_METADATA } from './utils';
import { GlobalStylesContext } from './context';

function mergeTreesCustomizer( _, srcValue ) {
// We only pass as arrays the presets,
// in which case we want the new array of values
// to override the old array (no merging).
if ( Array.isArray( srcValue ) ) {
return srcValue;
}
}

function mergeBaseAndUserConfigs( base, user ) {
return mergeWith( {}, base, user, mergeTreesCustomizer );
}

function addUserOriginToSettings( settingsToAdd ) {
const newSettings = cloneDeep( settingsToAdd );
PRESET_METADATA.forEach( ( { path } ) => {
const presetData = get( newSettings, path );
if ( presetData ) {
set( newSettings, path, {
user: presetData,
} );
}
} );
return newSettings;
}

function removeUserOriginFromSettings( settingsToRemove ) {
const newSettings = cloneDeep( settingsToRemove );
PRESET_METADATA.forEach( ( { path } ) => {
const presetData = get( newSettings, path );
if ( presetData ) {
set( newSettings, path, ( presetData ?? {} ).user );
}
} );
return newSettings;
}

function useGlobalStylesUserConfig() {
const { globalStylesId, content } = useSelect( ( select ) => {
const _globalStylesId = select( editSiteStore ).getSettings()
.__experimentalGlobalStylesUserEntityId;
return {
globalStylesId: _globalStylesId,
content: select( coreStore ).getEditedEntityRecord(
'postType',
'wp_global_styles',
_globalStylesId
)?.content,
};
}, [] );
const { getEditedEntityRecord } = useSelect( coreStore );
const { editEntityRecord } = useDispatch( coreStore );

const parseContent = ( contentToParse ) => {
let parsedConfig;
try {
parsedConfig = contentToParse ? JSON.parse( contentToParse ) : {};
// It is very important to verify if the flag isGlobalStylesUserThemeJSON is true.
// If it is not true the content was not escaped and is not safe.
if ( ! parsedConfig.isGlobalStylesUserThemeJSON ) {
parsedConfig = {};
} else {
parsedConfig = {
...parsedConfig,
settings: addUserOriginToSettings( parsedConfig.settings ),
};
}
} catch ( e ) {
/* eslint-disable no-console */
console.error( 'Global Styles User data is not valid' );
console.error( e );
/* eslint-enable no-console */
parsedConfig = {};
}

return parsedConfig;
};

const config = useMemo( () => {
return parseContent( content );
}, [ content ] );

const setConfig = useCallback(
( callback ) => {
const currentConfig = parseContent(
getEditedEntityRecord(
'postType',
'wp_global_styles',
globalStylesId
)?.content
);
const updatedConfig = callback( currentConfig );
editEntityRecord( 'postType', 'wp_global_styles', globalStylesId, {
content: JSON.stringify( {
...updatedConfig,
settings: removeUserOriginFromSettings(
updatedConfig.settings
),
} ),
} );
},
[ globalStylesId ]
);

return [ config, setConfig ];
}

function useGlobalStylesBaseConfig() {
const baseConfig = useSelect( ( select ) => {
return select( editSiteStore ).getSettings()
.__experimentalGlobalStylesBaseConfig;
}, [] );

return baseConfig;
}

function useGlobalStylesContext() {
const [ userConfig, setUserConfig ] = useGlobalStylesUserConfig();
const baseConfig = useGlobalStylesBaseConfig();
const mergedConfig = useMemo( () => {
return mergeBaseAndUserConfigs( baseConfig, userConfig );
}, [ userConfig, baseConfig ] );
const context = useMemo( () => {
return {
user: userConfig,
base: baseConfig,
merged: mergedConfig,
setUserConfig,
};
}, [ mergedConfig, userConfig, baseConfig, setUserConfig ] );

return context;
}

export function GlobalStylesProvider( { children } ) {
const context = useGlobalStylesContext();

return (
<GlobalStylesContext.Provider value={ context }>
{ children }
</GlobalStylesContext.Provider>
);
}
Loading

0 comments on commit 5572d59

Please sign in to comment.