Skip to content

Commit

Permalink
Fix useZoomOut inserter behavior (#67591)
Browse files Browse the repository at this point in the history
* Add e2e tests to cover scenarios for useZoomOut with the Inserter
* Add controlled concept to useZoomOut hook

---------

Co-authored-by: George Mamadashvili <[email protected]>
Co-authored-by: ajlende <[email protected]>
  • Loading branch information
3 people authored Dec 6, 2024
1 parent 00c32f4 commit cf528bf
Show file tree
Hide file tree
Showing 3 changed files with 333 additions and 43 deletions.
64 changes: 48 additions & 16 deletions packages/block-editor/src/hooks/use-zoom-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { useEffect, useRef } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -12,32 +12,64 @@ import { unlock } from '../lock-unlock';

/**
* A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode.
* Concepts:
* - If we most recently changed the zoom level for them (in or out), we always resetZoomLevel() level when unmounting.
* - If the user most recently changed the zoom level (manually toggling), we do nothing when unmounting.
*
* @param {boolean} zoomOut If we should enter into zoomOut mode or not
* @param {boolean} enabled If we should enter into zoomOut mode or not
*/
export function useZoomOut( zoomOut = true ) {
export function useZoomOut( enabled = true ) {
const { setZoomLevel, resetZoomLevel } = unlock(
useDispatch( blockEditorStore )
);
const { isZoomOut } = unlock( useSelect( blockEditorStore ) );

/**
* We need access to both the value and the function. The value is to trigger a useEffect hook
* and the function is to check zoom out within another hook without triggering a re-render.
*/
const { isZoomedOut, isZoomOut } = useSelect( ( select ) => {
const { isZoomOut: _isZoomOut } = unlock( select( blockEditorStore ) );
return {
isZoomedOut: _isZoomOut(),
isZoomOut: _isZoomOut,
};
}, [] );

const controlZoomLevelRef = useRef( false );
const isEnabledRef = useRef( enabled );

/**
* This hook tracks if the zoom state was changed manually by the user via clicking
* the zoom out button. We only want this to run when isZoomedOut changes, so we use
* a ref to track the enabled state.
*/
useEffect( () => {
const isZoomOutOnMount = isZoomOut();
// If the zoom state changed (isZoomOut) and it does not match the requested zoom
// state (zoomOut), then it means the user manually changed the zoom state while
// this hook was mounted, and we should no longer control the zoom state.
if ( isZoomedOut !== isEnabledRef.current ) {
controlZoomLevelRef.current = false;
}
}, [ isZoomedOut ] );

return () => {
if ( isZoomOutOnMount ) {
useEffect( () => {
isEnabledRef.current = enabled;

if ( enabled !== isZoomOut() ) {
controlZoomLevelRef.current = true;

if ( enabled ) {
setZoomLevel( 'auto-scaled' );
} else {
resetZoomLevel();
}
};
}, [] );

useEffect( () => {
if ( zoomOut ) {
setZoomLevel( 'auto-scaled' );
} else {
resetZoomLevel();
}
}, [ zoomOut, setZoomLevel, resetZoomLevel ] );

return () => {
// If we are controlling zoom level and are zoomed out, reset the zoom level.
if ( controlZoomLevelRef.current && isZoomOut() ) {
resetZoomLevel();
}
};
}, [ enabled, isZoomOut, resetZoomLevel, setZoomLevel ] );
}
1 change: 1 addition & 0 deletions test/e2e/specs/site-editor/preload.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
test.describe( 'Preload', () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.activateTheme( 'emptytheme' );
await requestUtils.resetPreferences();
} );

test.afterAll( async ( { requestUtils } ) => {
Expand Down
Loading

0 comments on commit cf528bf

Please sign in to comment.