Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iframe the template editor #31375

Merged
merged 9 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,8 @@ function gutenberg_extend_block_editor_styles_html() {
echo "<script>window.__editorStyles = $editor_styles</script>";
}
add_action( 'admin_footer-toplevel_page_gutenberg-edit-site', 'gutenberg_extend_block_editor_styles_html' );
add_action( 'admin_footer-post.php', 'gutenberg_extend_block_editor_styles_html' );
add_action( 'admin_footer-post-new.php', 'gutenberg_extend_block_editor_styles_html' );

/**
* Adds a polyfill for object-fit in environments which do not support it.
Expand Down
157 changes: 112 additions & 45 deletions packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ import {
__unstableEditorStyles as EditorStyles,
__experimentalUseEditorFeature as useEditorFeature,
__experimentalLayoutStyle as LayoutStyle,
__unstableUseMouseMoveTypingReset as useMouseMoveTypingReset,
__unstableIframe as Iframe,
} from '@wordpress/block-editor';
import { Popover, Button } from '@wordpress/components';
import { useRef } from '@wordpress/element';
import { Popover, Button } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useMergeRefs } from '@wordpress/compose';
import { useMergeRefs, useRefEffect } from '@wordpress/compose';
import { arrowLeft } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';

Expand All @@ -39,9 +41,44 @@ import { __ } from '@wordpress/i18n';
import BlockInspectorButton from './block-inspector-button';
import { store as editPostStore } from '../../store';

export default function VisualEditor( { styles } ) {
const ref = useRef();
function MaybeIframe( {
children,
contentRef,
isTemplateMode,
styles,
style,
} ) {
const ref = useMouseMoveTypingReset();
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this hook about?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's the same one we have in the site editor. It tracks mouse movement outside the iframe for setting isTyping to false. With #31280, it would be integrated in the block editor so the implementor doesn't need to think about it.


if ( ! isTemplateMode ) {
return (
<>
<EditorStyles styles={ styles } />
<div
ref={ contentRef }
className="editor-styles-wrapper"
style={ { width: '100%', height: '100%', ...style } }
>
{ children }
</div>
</>
);
}

return (
<Iframe
headHTML={ window.__editorStyles.html }
head={ <EditorStyles styles={ styles } /> }
ref={ ref }
contentRef={ contentRef }
style={ { width: '100%', height: '100%', display: 'block' } }
>
{ children }
</Iframe>
);
}

export default function VisualEditor( { styles } ) {
const { deviceType, isTemplateMode } = useSelect( ( select ) => {
const {
isEditingTemplate,
Expand All @@ -60,22 +97,20 @@ export default function VisualEditor( { styles } ) {
const { getSettings } = select( blockEditorStore );
return getSettings().supportsLayout;
}, [] );
const { clearSelectedBlock } = useDispatch( blockEditorStore );
const { setIsEditingTemplate } = useDispatch( editPostStore );
const desktopCanvasStyles = {
height: '100%',
width: '100%',
margin: 0,
// Add a constant padding for the typewritter effect. When typing at the
// bottom, there needs to be room to scroll up.
paddingBottom: hasMetaBoxes ? null : '40vh',
};
const templateModeStyles = {
...desktopCanvasStyles,
borderRadius: '2px',
borderRadius: '2px 2px 0 0',
border: '1px solid #ddd',
paddingBottom: null,
borderBottom: 0,
};
const resizedCanvasStyles = useResizeCanvas( deviceType );
const resizedCanvasStyles = useResizeCanvas( deviceType, isTemplateMode );
const defaultLayout = useEditorFeature( 'layout' );
const { contentSize, wideSize } = defaultLayout || {};
const alignments =
Expand All @@ -90,7 +125,16 @@ export default function VisualEditor( { styles } ) {
animatedStyles = resizedCanvasStyles;
}

const mergedRefs = useMergeRefs( [
let paddingBottom;

// Add a constant padding for the typewritter effect. When typing at the
// bottom, there needs to be room to scroll up.
if ( ! hasMetaBoxes && ! resizedCanvasStyles && ! isTemplateMode ) {
paddingBottom = '40vh';
}

const ref = useRef();
const contentRef = useMergeRefs( [
ref,
useClipboardHandler(),
useCanvasClickRedirect(),
Expand All @@ -101,12 +145,27 @@ export default function VisualEditor( { styles } ) {

const blockSelectionClearerRef = useBlockSelectionClearer( true );

// Allow scrolling "through" popovers over the canvas. This is only called
// for as long as the pointer is over a popover. Do not use React events
// because it will bubble through portals.
const toolWrapperRef = useRefEffect( ( node ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

If feels like this has the potential to break popovers with scrollbars though?

Copy link
Member Author

Choose a reason for hiding this comment

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

Those are rendered in the normal popover slot, which is outside this div. This slot is solely used for popovers that are placed over the content.

function onWheel( { deltaX, deltaY } ) {
ref.current.scrollBy( deltaX, deltaY );
}
node.addEventListener( 'wheel', onWheel );
return () => {
node.removeEventListener( 'wheel', onWheel );
};
}, [] );

return (
<motion.div
className={ classnames( 'edit-post-visual-editor', {
'is-template-mode': isTemplateMode,
} ) }
animate={ isTemplateMode ? { padding: '48px' } : { padding: 0 } }
animate={
isTemplateMode ? { padding: '48px 48px 0' } : { padding: 0 }
}
ref={ blockSelectionClearerRef }
>
{ themeSupportsLayout && (
Expand All @@ -115,52 +174,60 @@ export default function VisualEditor( { styles } ) {
layout={ defaultLayout }
/>
) }
<EditorStyles styles={ styles } />
<VisualEditorGlobalKeyboardShortcuts />
<Popover.Slot name="block-toolbar" />
{ isTemplateMode && (
<Button
className="edit-post-visual-editor__exit-template-mode"
icon={ arrowLeft }
onClick={ () => setIsEditingTemplate( false ) }
onClick={ () => {
clearSelectedBlock();
setIsEditingTemplate( false );
} }
>
{ __( 'Back' ) }
</Button>
) }
<motion.div
ref={ mergedRefs }
className="editor-styles-wrapper"
ref={ toolWrapperRef }
animate={ animatedStyles }
initial={ desktopCanvasStyles }
>
<AnimatePresence>
<motion.div
key={ isTemplateMode ? 'template' : 'post' }
initial={ { opacity: 0 } }
animate={ { opacity: 1 } }
>
<WritingFlow>
{ ! isTemplateMode && (
<div className="edit-post-visual-editor__post-title-wrapper">
<PostTitle />
</div>
) }
<BlockList
__experimentalLayout={
themeSupportsLayout
? {
type: 'default',
// Find a way to inject this in the support flag code (hooks).
alignments: themeSupportsLayout
? alignments
: undefined,
}
: undefined
}
/>
</WritingFlow>
</motion.div>
</AnimatePresence>
<Popover.Slot name="block-toolbar" />
<MaybeIframe
isTemplateMode={ isTemplateMode }
contentRef={ contentRef }
styles={ styles }
style={ { paddingBottom } }
>
<AnimatePresence>
<motion.div
key={ isTemplateMode ? 'template' : 'post' }
initial={ { opacity: 0 } }
animate={ { opacity: 1 } }
>
<WritingFlow>
{ ! isTemplateMode && (
<div className="edit-post-visual-editor__post-title-wrapper">
<PostTitle />
</div>
) }
<BlockList
__experimentalLayout={
themeSupportsLayout
? {
type: 'default',
// Find a way to inject this in the support flag code (hooks).
alignments: themeSupportsLayout
? alignments
: undefined,
}
: undefined
}
/>
</WritingFlow>
</motion.div>
</AnimatePresence>
</MaybeIframe>
</motion.div>
<__experimentalBlockSettingsMenuFirstItem>
{ ( { onClose } ) => (
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-post/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export function isSavingMetaBoxes( state ) {
* @return {string} Device type.
*/
export function __experimentalGetPreviewDeviceType( state ) {
return state.isEditingTemplate ? 'Desktop' : state.deviceType;
return state.deviceType;
}

/**
Expand Down