Skip to content

Commit

Permalink
[Mobile] Copy/Paste improvement (#27242)
Browse files Browse the repository at this point in the history
* Mobile - Notice - Use notices package

* Mobile - Clipboard refactor

* Mobile - ClipboardProvider - Use state

* Mobile - Move Clipboard context/provider into a singleton

* Mobile - Remove unused action and selector from the editor store. Add comment to explain getItems in the inserter menu

* Mobile - Block Actions Menu - Move function to consts, add local state to handle clipboard change
  • Loading branch information
Gerardo Pacheco authored Jan 4, 2021
1 parent 64729ac commit e073409
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { partial, first, castArray, last, compact } from 'lodash';
/**
* WordPress dependencies
*/
import { ToolbarButton, Picker } from '@wordpress/components';
import {
getClipboard,
setClipboard,
ToolbarButton,
Picker,
} from '@wordpress/components';
import {
getBlockType,
getDefaultBlockName,
Expand All @@ -19,7 +24,7 @@ import { __, sprintf } from '@wordpress/i18n';
import { withDispatch, withSelect } from '@wordpress/data';
import { withInstanceId, compose } from '@wordpress/compose';
import { moreHorizontalMobile } from '@wordpress/icons';
import { useRef } from '@wordpress/element';
import { useRef, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
Expand All @@ -40,15 +45,20 @@ const BlockActionsMenu = ( {
anchorNodeRef,
getBlocksByClientId,
selectedBlockClientId,
updateClipboard,
createInfoNotice,
createSuccessNotice,
duplicateBlock,
removeBlocks,
pasteBlock,
isPasteEnabled,
canInsertBlockType,
rootClientId,
} ) => {
const [ clipboard, setCurrentClipboard ] = useState( getClipboard() );
const pickerRef = useRef();
const moversOptions = { keys: [ 'icon', 'actionTitle' ] };
const clipboardBlock = clipboard && rawHandler( { HTML: clipboard } )[ 0 ];
const isPasteEnabled =
clipboardBlock &&
canInsertBlockType( clipboardBlock.name, rootClientId );

const {
actionTitle: {
Expand Down Expand Up @@ -120,11 +130,19 @@ const BlockActionsMenu = ( {
deleteOption,
] );

function onPasteBlock() {
if ( ! clipboard ) {
return;
}

pasteBlock( rawHandler( { HTML: clipboard } )[ 0 ] );
}

function onPickerSelect( value ) {
switch ( value ) {
case deleteOption.value:
onDelete();
createInfoNotice(
createSuccessNotice(
// translators: displayed right after the block is removed.
__( 'Block removed' )
);
Expand All @@ -140,31 +158,33 @@ const BlockActionsMenu = ( {
break;
case copyButtonOption.value:
const copyBlock = getBlocksByClientId( selectedBlockClientId );
updateClipboard( serialize( copyBlock ) );
createInfoNotice(
const serializedBlock = serialize( copyBlock );
setCurrentClipboard( serializedBlock );
setClipboard( serializedBlock );
createSuccessNotice(
// translators: displayed right after the block is copied.
__( 'Block copied' )
);
break;
case cutButtonOption.value:
const cutBlock = getBlocksByClientId( selectedBlockClientId );
updateClipboard( serialize( cutBlock ) );
setClipboard( serialize( cutBlock ) );
removeBlocks( selectedBlockClientId );
createInfoNotice(
createSuccessNotice(
// translators: displayed right after the block is cut.
__( 'Block cut' )
);
break;
case pasteButtonOption.value:
pasteBlock();
createInfoNotice(
onPasteBlock();
createSuccessNotice(
// translators: displayed right after the block is pasted.
__( 'Block pasted' )
);
break;
case duplicateButtonOption.value:
duplicateBlock();
createInfoNotice(
createSuccessNotice(
// translators: displayed right after the block is duplicated.
__( 'Block duplicated' )
);
Expand Down Expand Up @@ -228,7 +248,6 @@ export default compose(
getSelectedBlockClientIds,
canInsertBlockType,
} = select( 'core/block-editor' );
const { getClipboard } = select( 'core/editor' );
const normalizedClientIds = castArray( clientIds );
const block = getBlock( normalizedClientIds );
const blockName = getBlockName( normalizedClientIds );
Expand All @@ -250,13 +269,6 @@ export default compose(
const isEmptyDefaultBlock =
isExactlyOneBlock && isDefaultBlock && isEmptyContent;

const clipboard = getClipboard();
const clipboardBlock =
clipboard && rawHandler( { HTML: clipboard } )[ 0 ];
const isPasteEnabled =
clipboardBlock &&
canInsertBlockType( clipboardBlock.name, rootClientId );

return {
isFirst: firstIndex === 0,
isLast: lastIndex === blockOrder.length - 1,
Expand All @@ -266,16 +278,11 @@ export default compose(
getBlocksByClientId,
selectedBlockClientId: getSelectedBlockClientIds(),
currentIndex: firstIndex,
isPasteEnabled,
clipboardBlock,
canInsertBlockType,
};
} ),
withDispatch(
(
dispatch,
{ clientIds, rootClientId, currentIndex, clipboardBlock },
{ select }
) => {
( dispatch, { clientIds, rootClientId, currentIndex }, { select } ) => {
const {
moveBlocksDown,
moveBlocksUp,
Expand All @@ -285,25 +292,22 @@ export default compose(
replaceBlocks,
} = dispatch( 'core/block-editor' );
const { openGeneralSidebar } = dispatch( 'core/edit-post' );
const { updateClipboard, createInfoNotice } = dispatch(
'core/editor'
);
const { getBlockSelectionEnd, getBlock } = select(
'core/block-editor'
);
const { createSuccessNotice } = dispatch( 'core/notices' );

return {
onMoveDown: partial( moveBlocksDown, clientIds, rootClientId ),
onMoveUp: partial( moveBlocksUp, clientIds, rootClientId ),
openGeneralSidebar: () =>
openGeneralSidebar( 'edit-post/block' ),
updateClipboard,
createInfoNotice,
createSuccessNotice,
duplicateBlock() {
return duplicateBlocks( clientIds );
},
removeBlocks,
pasteBlock: () => {
pasteBlock: ( clipboardBlock ) => {
const canReplaceBlock = isUnmodifiedDefaultBlock(
getBlock( getBlockSelectionEnd() )
);
Expand Down
63 changes: 41 additions & 22 deletions packages/block-editor/src/components/inserter/menu.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
BottomSheet,
BottomSheetConsumer,
InserterButton,
getClipboard,
} from '@wordpress/components';

/**
Expand Down Expand Up @@ -115,6 +116,42 @@ export class InserterMenu extends Component {
this.setState( { numberOfColumns, itemWidth, maxWidth } );
}

/**
* Processes the inserter items to check
* if there's any copied block in the clipboard
* to add it as an extra item
*/
getItems() {
const {
items,
canInsertBlockType,
destinationRootClientId,
getBlockType,
} = this.props;

const clipboard = getClipboard();
const clipboardBlock =
clipboard && rawHandler( { HTML: clipboard } )[ 0 ];
const shouldAddClipboardBlock =
clipboardBlock &&
canInsertBlockType( clipboardBlock.name, destinationRootClientId );

return shouldAddClipboardBlock
? [
{
...pick( getBlockType( clipboardBlock.name ), [
'name',
'icon',
] ),
id: 'clipboard',
initialAttributes: clipboardBlock.attributes,
innerBlocks: clipboardBlock.innerBlocks,
},
...items,
]
: items;
}

renderItem( { item } ) {
const { itemWidth, maxWidth } = this.state;
const { onSelect } = this.props;
Expand All @@ -129,8 +166,8 @@ export class InserterMenu extends Component {
}

render() {
const { items } = this.props;
const { numberOfColumns } = this.state;
const items = this.getItems();

return (
<BottomSheet
Expand Down Expand Up @@ -186,7 +223,6 @@ export default compose(
canInsertBlockType,
} = select( 'core/block-editor' );
const { getChildBlockNames, getBlockType } = select( blocksStore );
const { getClipboard } = select( 'core/editor' );

let destinationRootClientId = rootClientId;
if ( ! destinationRootClientId && ! clientId && ! isAppender ) {
Expand All @@ -203,31 +239,14 @@ export default compose(
const {
__experimentalShouldInsertAtTheTop: shouldInsertAtTheTop,
} = getSettings();
const clipboard = getClipboard();
const clipboardBlock =
clipboard && rawHandler( { HTML: clipboard } )[ 0 ];
const shouldAddClipboardBlock =
clipboardBlock &&
canInsertBlockType( clipboardBlock.name, destinationRootClientId );

return {
rootChildBlocks: getChildBlockNames( destinationRootBlockName ),
items: shouldAddClipboardBlock
? [
{
...pick( getBlockType( clipboardBlock.name ), [
'name',
'icon',
] ),
id: 'clipboard',
initialAttributes: clipboardBlock.attributes,
innerBlocks: clipboardBlock.innerBlocks,
},
...getInserterItems( destinationRootClientId ),
]
: getInserterItems( destinationRootClientId ),
items: getInserterItems( destinationRootClientId ),
destinationRootClientId,
shouldInsertAtTheTop,
getBlockType,
canInsertBlockType,
};
} ),
withDispatch( ( dispatch, ownProps, { select } ) => {
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export { default as LinkSettingsNavigation } from './mobile/link-settings/link-s
export { default as Image, IMAGE_DEFAULT_FOCAL_POINT } from './mobile/image';
export { default as ImageEditingButton } from './mobile/image/image-editing-button';
export { default as InserterButton } from './mobile/inserter-button';
export { setClipboard, getClipboard } from './mobile/clipboard';

// Utils
export { colorsUtils } from './mobile/color-settings/utils';
Expand Down
18 changes: 18 additions & 0 deletions packages/components/src/mobile/clipboard/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const createClipboard = () => {
let currentClipboard;

const setClipboard = ( clipboard ) => {
currentClipboard = clipboard;
};

const getClipboard = () => currentClipboard;

return {
setClipboard,
getClipboard,
};
};

const clipboard = createClipboard();

export const { setClipboard, getClipboard } = clipboard;
5 changes: 2 additions & 3 deletions packages/components/src/notice/list.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ class NoticeList extends Component {

export default compose( [
withSelect( ( select ) => {
const { getNotices } = select( 'core/editor' );
const { getNotices } = select( 'core/notices' );

return {
notices: getNotices(),
};
} ),
withDispatch( ( dispatch ) => {
const { removeNotice, removeAllNotices } = dispatch( 'core/editor' );
const { removeNotice } = dispatch( 'core/notices' );

return {
removeNotice,
removeAllNotices,
};
} ),
] )( NoticeList );
9 changes: 4 additions & 5 deletions packages/editor/src/components/provider/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class NativeEditorProvider extends Component {

this.subscriptionParentShowNotice = subscribeShowNotice(
( payload ) => {
this.props.createInfoNotice( payload.message );
this.props.createSuccessNotice( payload.message );
}
);
}
Expand Down Expand Up @@ -307,9 +307,7 @@ export default compose( [
};
} ),
withDispatch( ( dispatch ) => {
const { editPost, resetEditorBlocks, createInfoNotice } = dispatch(
'core/editor'
);
const { editPost, resetEditorBlocks } = dispatch( 'core/editor' );
const {
updateSettings,
clearSelectedBlock,
Expand All @@ -318,13 +316,14 @@ export default compose( [
} = dispatch( 'core/block-editor' );
const { switchEditorMode } = dispatch( 'core/edit-post' );
const { addEntities, receiveEntityRecords } = dispatch( 'core' );
const { createSuccessNotice } = dispatch( 'core/notices' );

return {
updateSettings,
addEntities,
clearSelectedBlock,
insertBlock,
createInfoNotice,
createSuccessNotice,
editTitle( title ) {
editPost( { title } );
},
Expand Down
Loading

0 comments on commit e073409

Please sign in to comment.