Skip to content

Commit

Permalink
Merge pull request #200 from wordpress-mobile/issue/167-block-merge-i…
Browse files Browse the repository at this point in the history
…ntroduce-JS-logic

Blocks Merging - Introduce the JS callback
  • Loading branch information
diegoreymendez authored Oct 29, 2018
2 parents 0bfa3a6 + 4419ee7 commit 19feb55
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 2 deletions.
2 changes: 1 addition & 1 deletion gutenberg
Submodule gutenberg updated 246 files
4 changes: 4 additions & 0 deletions src/app/AppContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
deleteBlockAction,
createBlockAction,
parseBlocksAction,
mergeBlocksAction,
} from '../store/actions';
import MainApp from './MainApp';

Expand Down Expand Up @@ -41,6 +42,9 @@ const mapDispatchToProps = ( dispatch, ownProps ) => {
parseBlocksAction: ( html ) => {
dispatch( parseBlocksAction( html ) );
},
mergeBlocksAction: ( blockOneClientId, blockTwoClientId, block ) => {
dispatch( mergeBlocksAction( blockOneClientId, blockTwoClientId, block ) );
},
};
};

Expand Down
2 changes: 2 additions & 0 deletions src/block-management/block-holder.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PropsType = BlockType & {
onToolbarButtonPressed: ( button: number, clientId: string ) => void,
onBlockHolderPressed: ( clientId: string ) => void,
insertBlocksAfter: ( blocks: Array<Object> ) => void,
mergeBlocks: ( forward: boolean ) => void,
};

type StateType = {
Expand Down Expand Up @@ -71,6 +72,7 @@ export default class BlockHolder extends React.Component<PropsType, StateType> {
this.props.onChange( this.props.clientId, { ...this.props.attributes, ...attrs } )
}
insertBlocksAfter={ this.props.insertBlocksAfter }
mergeBlocks={ this.props.mergeBlocks }
isSelected={ this.props.focused }
style={ style }
/>
Expand Down
73 changes: 72 additions & 1 deletion src/block-management/block-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import BlockPicker from './block-picker';
import HTMLTextInput from '../components/html-text-input';

// Gutenberg imports
import { createBlock } from '@wordpress/blocks';
import { createBlock, getBlockType, switchToBlockType } from '@wordpress/blocks';

export type BlockListType = {
onChange: ( clientId: string, attributes: mixed ) => void,
Expand All @@ -24,6 +24,7 @@ export type BlockListType = {
deleteBlockAction: string => mixed,
createBlockAction: ( string, BlockType, string ) => mixed,
parseBlocksAction: string => mixed,
mergeBlocksAction: ( string, string, BlockType ) => mixed,
blocks: Array<BlockType>,
aztechtml: string,
refresh: boolean,
Expand Down Expand Up @@ -154,6 +155,73 @@ export default class BlockManager extends React.Component<PropsType, StateType>
this.props.focusBlockAction( newBlock.clientId ); // this not working atm
}

mergeBlocks( clientId: string, forward: boolean ) {
// find currently focused block
const focusedItemIndex = this.getDataSourceIndexFromClientId( clientId );
// Do nothing when it's the first block and backspace is pressed
// Do nothing when it's the last block and delete is pressed
if (
( ! forward && focusedItemIndex === 0 ) ||
( forward && ! focusedItemIndex === this.state.dataSource.size() - 1 )
) {
return;
}

let blockA = null;
let blockB = null;
if ( forward ) {
blockA = this.state.dataSource.get( focusedItemIndex );
blockB = this.state.dataSource.get( focusedItemIndex + 1 );
} else {
blockA = this.state.dataSource.get( focusedItemIndex - 1 );
blockB = this.state.dataSource.get( focusedItemIndex );
}

const blockType = getBlockType( blockA.name );

// Only focus the previous block if it's not mergeable
if ( ! blockType.merge ) {
// TO DO: move the focus to the prev block
return;
}

// TODO: there is a problem with block transformation
// let's stop here until we fix the problems with block transformation routine
if ( blockA.name !== blockB.name ) {
return;
}

// We can only merge blocks with similar types
// thus, we transform the block to merge first
const blocksWithTheSameType = blockA.name === blockB.name ?
[ blockB ] :
switchToBlockType( blockB, blockA.name );

// If the block types can not match, do nothing
if ( ! blocksWithTheSameType || ! blocksWithTheSameType.length ) {
return;
}

// Calling the merge to update the attributes and remove the block to be merged
const updatedAttributes = blockType.merge(
blockA.attributes,
blocksWithTheSameType[ 0 ].attributes
);

const newBlock = {
...blockA,
attributes: {
...blockA.attributes,
...updatedAttributes,
},
};
newBlock.focused = true;

// set it into the datasource, and use the same object instance to send it to props/redux
this.state.dataSource.splice( this.getDataSourceIndexFromClientId( blockA.clientId ), 2, newBlock );
this.props.mergeBlocksAction( blockA.clientId, blockB.clientId, newBlock );
}

onChange( clientId: string, attributes: mixed ) {
// Update Redux store
this.props.onChange( clientId, attributes );
Expand Down Expand Up @@ -270,6 +338,9 @@ export default class BlockManager extends React.Component<PropsType, StateType>
insertBlocksAfter={ ( blocks ) =>
this.insertBlocksAfter.bind( this )( value.item.clientId, blocks )
}
mergeBlocks={ ( forward = false ) =>
this.mergeBlocks.bind( this )( value.item.clientId, forward )
}
{ ...value.item }
/>
{ this.state.blockTypePickerVisible && value.item.focused && insertHere }
Expand Down
1 change: 1 addition & 0 deletions src/store/actions/ActionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export default {
DELETE: 'BLOCK_DELETE_ACTION',
CREATE: 'BLOCK_CREATE_ACTION',
PARSE: 'BLOCK_PARSE_ACTION',
MERGE: 'BLOCKS_MERGE_ACTION',
},
};
14 changes: 14 additions & 0 deletions src/store/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export type ParseActionType = string => {
html: string,
};

export type BlocksActionType = ( string, string, BlockType ) => {
type: $Values<typeof ActionTypes.BLOCK>,
blockOneClientId: string,
blockTwoClientId: string,
block: BlockType,
};

export function updateBlockAttributes( clientId: string, attributes: mixed ) {
return {
type: ActionTypes.BLOCK.UPDATE_ATTRIBUTES,
Expand Down Expand Up @@ -62,3 +69,10 @@ export const parseBlocksAction: ParseActionType = ( html ) => ( {
type: ActionTypes.BLOCK.PARSE,
html,
} );

export const mergeBlocksAction: BlocksActionType = ( blockOneClientId, blockTwoClientId, block ) => ( {
type: ActionTypes.BLOCK.MERGE,
blockOneClientId,
blockTwoClientId,
block,
} );
5 changes: 5 additions & 0 deletions src/store/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ export const reducer = (
const parsed = parse( action.html );
return { blocks: parsed, refresh: ! state.refresh, fullparse: true };
}
case ActionTypes.BLOCK.MERGE: {
const index = findBlockIndex( blocks, action.blockOneClientId );
blocks.splice( index, 2, action.block );
return { blocks: blocks, refresh: ! state.refresh };
}
default:
return state;
}
Expand Down

0 comments on commit 19feb55

Please sign in to comment.