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

Decouple "zoom/scaling the canvas" from zoom out mode (without mode rename) #65482

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from
4 changes: 2 additions & 2 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1027,11 +1027,11 @@ _Parameters_

### useZoomOut

A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode.
A hook used to set the zoomed out view, invoking the hook sets the mode.

_Parameters_

- _zoomOut_ `boolean`: If we should enter into zoomOut mode or not
- _zoomOut_ `boolean`: If we should zoom out or not.

### Warning

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ import { unlock } from '../../../lock-unlock';
* @param {string} clientId Block client ID.
*/
export function useZoomOutModeExit( { editorMode } ) {
const { getSettings } = useSelect( blockEditorStore );
const { __unstableSetEditorMode } = unlock(
const { getSettings, isZoomOut } = unlock( useSelect( blockEditorStore ) );
const { __unstableSetEditorMode, resetZoomOut } = unlock(
useDispatch( blockEditorStore )
);

return useRefEffect(
( node ) => {
if ( editorMode !== 'zoom-out' ) {
// In "compose" mode.
const composeMode = editorMode === 'zoom-out' && isZoomOut();

if ( ! composeMode ) {
return;
}

Expand All @@ -39,6 +42,7 @@ export function useZoomOutModeExit( { editorMode } ) {
__experimentalSetIsInserterOpened( false );
}
__unstableSetEditorMode( 'edit' );
resetZoomOut();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import BlockDraggable from '../block-draggable';
import BlockMover from '../block-mover';
import Shuffle from '../block-toolbar/shuffle';
import NavigableToolbar from '../navigable-toolbar';
import { unlock } from '../../lock-unlock';

export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
const selected = useSelect(
Expand Down Expand Up @@ -84,8 +85,9 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
setIsInserterOpened,
} = selected;

const { removeBlock, __unstableSetEditorMode } =
useDispatch( blockEditorStore );
const { removeBlock, __unstableSetEditorMode, resetZoomOut } = unlock(
useDispatch( blockEditorStore )
);

const classNames = clsx( 'zoom-out-toolbar', {
'is-block-moving-mode': !! blockMovingMode,
Expand Down Expand Up @@ -144,6 +146,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
setIsInserterOpened( false );
}
__unstableSetEditorMode( 'edit' );
resetZoomOut();
__unstableContentRef.current?.focus();
} }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Icon, edit as editIcon } from '@wordpress/icons';
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

const selectIcon = (
<SVG
Expand All @@ -35,7 +36,9 @@ function ToolSelector( props, ref ) {
( select ) => select( blockEditorStore ).__unstableGetEditorMode(),
[]
);
const { __unstableSetEditorMode } = useDispatch( blockEditorStore );
const { __unstableSetEditorMode } = unlock(
useDispatch( blockEditorStore )
);

return (
<Dropdown
Expand Down
45 changes: 23 additions & 22 deletions packages/block-editor/src/hooks/use-zoom-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,47 @@ import { useEffect, useRef } from '@wordpress/element';
* Internal dependencies
*/
import { store as blockEditorStore } from '../store';
import { unlock } from '../lock-unlock';

/**
* A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode.
* A hook used to set the zoomed out view, invoking the hook sets the mode.
Comment on lines -13 to +14
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This hook used to set the mode to zoom-out. Now it just sets the zoom level. Is that what we want? It's only used in a single location in Core.

Personally I think it should be deprecated as an API.

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we need the hook for all the effect management it does?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess it could be useful for "zooming the canvas". But note how it's usage has already changed from managing "modes" to managing "scale". It's just a premature API in my opinion.

*
* @param {boolean} zoomOut If we should enter into zoomOut mode or not
* @param {boolean} zoomOut If we should zoom out or not.
*/
export function useZoomOut( zoomOut = true ) {
const { __unstableSetEditorMode } = useDispatch( blockEditorStore );
const { __unstableGetEditorMode } = useSelect( blockEditorStore );
const { setZoomOut } = unlock( useDispatch( blockEditorStore ) );
const { isZoomOut } = unlock( useSelect( blockEditorStore ) );

const originalEditingModeRef = useRef( null );
const mode = __unstableGetEditorMode();
const originalIsZoomOutRef = useRef( null );
const currentZoomOutState = isZoomOut();

useEffect( () => {
// Only set this on mount so we know what to return to when we unmount.
if ( ! originalEditingModeRef.current ) {
originalEditingModeRef.current = mode;
if ( ! originalIsZoomOutRef.current ) {
originalIsZoomOutRef.current = currentZoomOutState;
}

return () => {
// We need to use __unstableGetEditorMode() here and not `mode`, as mode may not update on unmount
if (
__unstableGetEditorMode() === 'zoom-out' &&
__unstableGetEditorMode() !== originalEditingModeRef.current
) {
__unstableSetEditorMode( originalEditingModeRef.current );
// We need to use isZoomOut() here and not `currentZoomOutState`, as currentZoomOutState may not update on unmount
if ( isZoomOut() && isZoomOut() !== originalIsZoomOutRef.current ) {
setZoomOut( originalIsZoomOutRef.current );
}
};
}, [] );
}, [ currentZoomOutState, isZoomOut, setZoomOut ] );

// The effect opens the zoom-out view if we want it open and it's not currently in zoom-out mode.
// The effect opens the zoom-out view if we want it open and the canvas is not currently zoomed-out.
useEffect( () => {
if ( zoomOut && mode !== 'zoom-out' ) {
__unstableSetEditorMode( 'zoom-out' );
if ( zoomOut && currentZoomOutState === false ) {
// __unstableSetEditorMode( 'compose' );
setZoomOut( true );
} else if (
! zoomOut &&
__unstableGetEditorMode() === 'zoom-out' &&
originalEditingModeRef.current !== mode
isZoomOut() &&
originalIsZoomOutRef.current !== currentZoomOutState
) {
__unstableSetEditorMode( originalEditingModeRef.current );
setZoomOut( originalIsZoomOutRef.current );
}
}, [ __unstableGetEditorMode, __unstableSetEditorMode, zoomOut ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes.
// currentZoomOutState is deliberately excluded from the dependencies so that the effect does not run when mode changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ isZoomOut, setZoomOut, zoomOut ] );
}
33 changes: 33 additions & 0 deletions packages/block-editor/src/store/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,36 @@ export const modifyContentLockBlock =
focusModeToRevert
);
};

/**
* Sets the zoom level.
*
* @param {number} zoom the new zoom level
* @return {Object} Action object.
*/
export function setZoomOut( zoom = 50 ) {
let zoomValue;

if ( zoom === true ) {
zoomValue = 50;
} else if ( zoom === false ) {
zoomValue = 100; // Considered as a reset
} else {
zoomValue = zoom;
}

return {
type: 'SET_ZOOM_OUT',
zoom: zoomValue,
};
}

/**
* Resets the Zoom state.
* @return {Object} Action object.
*/
export function resetZoomOut() {
return {
type: 'RESET_ZOOM',
};
}
getdave marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 20 additions & 0 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,23 @@ export function isZoomOutMode( state ) {
export function getSectionRootClientId( state ) {
return state.settings?.[ sectionRootClientIdKey ];
}

/**
* Returns the zoom out state.
*
* @param {Object} state Global application state.
* @return {boolean} The zoom out state.
*/
export function getZoomLevel( state ) {
return state.zoomLevel;
}

/**
* Returns whether the editor is considered zoomed out.
*
* @param {Object} state Global application state.
* @return {boolean} Whether the editor is zoomed.
*/
export function isZoomOut( state ) {
return getZoomLevel( state ) < 100;
}
Comment on lines +570 to +582
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's make the nomenclature consistent. Is it "zoom-out" or "zoom-level"? type and naming need to be consistent.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is all right, zoom out is any zoom level less than 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

20 changes: 20 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2085,6 +2085,25 @@ export function hoveredBlockClientId( state = false, action ) {
return state;
}

/**
* Reducer setting zoom out state.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
export function zoomLevel( state = 100, action ) {
switch ( action.type ) {
case 'SET_ZOOM_OUT':
return action.zoom;
case 'RESET_ZOOM':
return 100;
}

return state;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's make the nomenclature consistent. Is it "zoom-out" or "zoom-level"? type and naming need to be consistent.

Copy link
Contributor

Choose a reason for hiding this comment

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

Zoom out is anytime zoom level is less than 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's usually best to avoid using floating point numbers in JS. I went for 100 to mirror the traditional zoom scale of 0-100.

Is there a reason why you are suggesting 1? Is it used somewhere else already?

const combinedReducers = combineReducers( {
blocks,
isDragging,
Expand Down Expand Up @@ -2118,6 +2137,7 @@ const combinedReducers = combineReducers( {
openedBlockSettingsMenu,
registeredInserterMediaCategories,
hoveredBlockClientId,
zoomLevel,
} );

function withAutomaticChangeReset( reducer ) {
Expand Down
10 changes: 6 additions & 4 deletions packages/editor/src/components/editor-interface/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import TextEditor from '../text-editor';
import VisualEditor from '../visual-editor';
import EditorContentSlotFill from './content-slot-fill';

import { unlock } from '../../lock-unlock';

const interfaceLabels = {
/* translators: accessibility text for the editor top bar landmark region. */
header: __( 'Editor top bar' ),
Expand Down Expand Up @@ -71,12 +73,13 @@ export default function EditorInterface( {
nextShortcut,
showBlockBreadcrumbs,
documentLabel,
blockEditorMode,
isZoomOut,
} = useSelect( ( select ) => {
const { get } = select( preferencesStore );
const { getEditorSettings, getPostTypeLabel } = select( editorStore );
const editorSettings = getEditorSettings();
const postTypeLabel = getPostTypeLabel();
const { isZoomOut: _isZoomOut } = unlock( select( blockEditorStore ) );

return {
mode: select( editorStore ).getEditorMode(),
Expand All @@ -94,8 +97,7 @@ export default function EditorInterface( {
showBlockBreadcrumbs: get( 'core', 'showBlockBreadcrumbs' ),
// translators: Default label for the Document in the Block Breadcrumb.
documentLabel: postTypeLabel || _x( 'Document', 'noun' ),
blockEditorMode:
select( blockEditorStore ).__unstableGetEditorMode(),
isZoomOut: _isZoomOut(),
};
}, [] );
const isLargeViewport = useViewportMatch( 'medium' );
Expand Down Expand Up @@ -206,7 +208,7 @@ export default function EditorInterface( {
isLargeViewport &&
showBlockBreadcrumbs &&
isRichEditingEnabled &&
blockEditorMode !== 'zoom-out' &&
! isZoomOut &&
mode === 'visual' && (
<BlockBreadcrumb rootLabelText={ documentLabel } />
)
Expand Down
14 changes: 8 additions & 6 deletions packages/editor/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,19 @@ function VisualEditor( {
hasRootPaddingAwareAlignments,
themeHasDisabledLayoutStyles,
themeSupportsLayout,
isZoomOutMode,
isZoomedOut,
} = useSelect( ( select ) => {
const { getSettings, __unstableGetEditorMode } =
select( blockEditorStore );
const { getSettings, isZoomOut: _isZoomOut } = unlock(
select( blockEditorStore )
);

const _settings = getSettings();
return {
themeHasDisabledLayoutStyles: _settings.disableLayoutStyles,
themeSupportsLayout: _settings.supportsLayout,
hasRootPaddingAwareAlignments:
_settings.__experimentalFeatures?.useRootPaddingAwareAlignments,
isZoomOutMode: __unstableGetEditorMode() === 'zoom-out',
isZoomedOut: _isZoomOut(),
};
}, [] );

Expand Down Expand Up @@ -336,7 +338,7 @@ function VisualEditor( {
] );

const zoomOutProps =
isZoomOutMode && ! isTabletViewport
isZoomedOut && ! isTabletViewport
? {
scale: 'default',
frameSize: '48px',
Expand All @@ -355,7 +357,7 @@ function VisualEditor( {
// Disable resizing in mobile viewport.
! isMobileViewport &&
// Dsiable resizing in zoomed-out mode.
! isZoomOutMode;
! isZoomedOut;
const shouldIframe =
! disableIframe || [ 'Tablet', 'Mobile' ].includes( deviceType );

Expand Down
19 changes: 13 additions & 6 deletions packages/editor/src/components/zoom-out-toggle/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,31 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { square as zoomOutIcon } from '@wordpress/icons';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';

const ZoomOutToggle = () => {
const { isZoomOutMode } = useSelect( ( select ) => ( {
isZoomOutMode:
select( blockEditorStore ).__unstableGetEditorMode() === 'zoom-out',
const { isZoomOut } = useSelect( ( select ) => ( {
isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(),
} ) );

const { __unstableSetEditorMode } = useDispatch( blockEditorStore );
const { setZoomOut, __unstableSetEditorMode } = unlock(
useDispatch( blockEditorStore )
);

const handleZoomOut = () => {
__unstableSetEditorMode( isZoomOutMode ? 'edit' : 'zoom-out' );
setZoomOut( isZoomOut ? false : true );
__unstableSetEditorMode( isZoomOut ? 'edit' : 'zoom-out' );
};

return (
<Button
onClick={ handleZoomOut }
icon={ zoomOutIcon }
label={ __( 'Toggle Zoom Out' ) }
isPressed={ isZoomOutMode }
isPressed={ isZoomOut }
size="compact"
/>
);
Expand Down
Loading