Skip to content

Commit

Permalink
Record selection changes in history (undo)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Jul 18, 2019
1 parent c323235 commit ee24ec0
Show file tree
Hide file tree
Showing 16 changed files with 262 additions and 158 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,8 @@ content reflected as an edit in state.
_Parameters_

- _blocks_ `Array`: Array of blocks.
- _selectionStart_ `Array`: Selection start object.
- _selectionEnd_ `Array`: Selection end object.

_Returns_

Expand Down
24 changes: 24 additions & 0 deletions docs/designers-developers/developers/data/data-core-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,30 @@ _Returns_

- `Array`: Block list.

<a name="getEditorSelectionEnd" href="#getEditorSelectionEnd">#</a> **getEditorSelectionEnd**

Return the current selection end object.

_Parameters_

- _state_ `Object`:

_Returns_

- `Array`: Selection end object.

<a name="getEditorSelectionStart" href="#getEditorSelectionStart">#</a> **getEditorSelectionStart**

Return the current selection start object.

_Parameters_

- _state_ `Object`:

_Returns_

- `Array`: Selection start object.

<a name="getEditorSettings" href="#getEditorSettings">#</a> **getEditorSettings**

Returns the post editor settings.
Expand Down
13 changes: 10 additions & 3 deletions packages/block-editor/src/components/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class BlockEditorProvider extends Component {
settings,
updateSettings,
value,
selectionStart,
selectionEnd,
resetBlocks,
registry,
} = this.props;
Expand Down Expand Up @@ -49,7 +51,7 @@ class BlockEditorProvider extends Component {
// subsequent renders.
this.isSyncingOutcomingValue = null;
this.isSyncingIncomingValue = value;
resetBlocks( value );
resetBlocks( value, selectionStart, selectionEnd );
}
}

Expand Down Expand Up @@ -78,6 +80,8 @@ class BlockEditorProvider extends Component {

const {
getBlocks,
getSelectionStart,
getSelectionEnd,
isLastBlockChangePersistent,
__unstableIsLastBlockChangeIgnored,
} = registry.select( 'core/block-editor' );
Expand Down Expand Up @@ -120,10 +124,13 @@ class BlockEditorProvider extends Component {
blocks = newBlocks;
isPersistent = newIsPersistent;

const selectionStart = getSelectionStart();
const selectionEnd = getSelectionEnd();

if ( isPersistent ) {
onChange( blocks );
onChange( blocks, selectionStart, selectionEnd );
} else {
onInput( blocks );
onInput( blocks, selectionStart, selectionEnd );
}
}
} );
Expand Down
9 changes: 6 additions & 3 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ function* ensureDefaultBlock() {
* reset to the specified array of blocks, taking precedence over any other
* content reflected as an edit in state.
*
* @param {Array} blocks Array of blocks.
* @param {Array} blocks Array of blocks.
* @param {Array} selectionStart Selection start object.
* @param {Array} selectionEnd Selection end object.
*
* @return {Object} Action object.
*/
export function resetBlocks( blocks ) {
export function resetBlocks( blocks, selectionStart, selectionEnd ) {
return {
type: 'RESET_BLOCKS',
blocks,
selectionStart,
selectionEnd,
};
}

Expand Down Expand Up @@ -704,4 +708,3 @@ export function __unstableSaveReusableBlock( id, updatedId ) {
export function __unstableMarkLastChangeAsPersistent() {
return { type: 'MARK_LAST_CHANGE_AS_PERSISTENT' };
}

97 changes: 55 additions & 42 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -910,15 +910,6 @@ export function isCaretWithinFormattedText( state = false, action ) {
return state;
}

const BLOCK_SELECTION_EMPTY_OBJECT = {};
const BLOCK_SELECTION_INITIAL_STATE = {
start: BLOCK_SELECTION_EMPTY_OBJECT,
end: BLOCK_SELECTION_EMPTY_OBJECT,
isMultiSelecting: false,
isEnabled: true,
initialPosition: null,
};

/**
* Reducer returning the block selection's state.
*
Expand All @@ -927,34 +918,18 @@ const BLOCK_SELECTION_INITIAL_STATE = {
*
* @return {Object} Updated state.
*/
export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action ) {
export function blockSelection( state = { start: {}, end: {} }, action ) {
switch ( action.type ) {
case 'CLEAR_SELECTED_BLOCK':
return BLOCK_SELECTION_INITIAL_STATE;
case 'START_MULTI_SELECT':
if ( state.isMultiSelecting ) {
return state;
case 'CLEAR_SELECTED_BLOCK': {
if ( state.start.clientId || state.end.clientId ) {
return { start: {}, end: {} };
}

return {
...state,
isMultiSelecting: true,
initialPosition: null,
};
case 'STOP_MULTI_SELECT':
if ( ! state.isMultiSelecting ) {
return state;
}
return state;
}

return {
...state,
isMultiSelecting: false,
initialPosition: null,
};
case 'MULTI_SELECT':
return {
...BLOCK_SELECTION_INITIAL_STATE,
isMultiSelecting: state.isMultiSelecting,
start: { clientId: action.start },
end: { clientId: action.end },
};
Expand All @@ -967,7 +942,6 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
}

return {
...BLOCK_SELECTION_INITIAL_STATE,
initialPosition: action.initialPosition,
start: { clientId: action.clientId },
end: { clientId: action.clientId },
Expand All @@ -976,7 +950,6 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
case 'INSERT_BLOCKS': {
if ( action.updateSelection ) {
return {
...BLOCK_SELECTION_INITIAL_STATE,
start: { clientId: action.blocks[ 0 ].clientId },
end: { clientId: action.blocks[ 0 ].clientId },
};
Expand All @@ -993,7 +966,7 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
return state;
}

return BLOCK_SELECTION_INITIAL_STATE;
return { start: {}, end: {} };
case 'REPLACE_BLOCKS': {
if ( action.clientIds.indexOf( state.start.clientId ) === -1 ) {
return state;
Expand All @@ -1003,7 +976,7 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
const blockToSelect = action.blocks[ indexToSelect ];

if ( ! blockToSelect ) {
return BLOCK_SELECTION_INITIAL_STATE;
return { start: {}, end: {} };
}

if (
Expand All @@ -1014,19 +987,12 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
}

return {
...BLOCK_SELECTION_INITIAL_STATE,
start: { clientId: blockToSelect.clientId },
end: { clientId: blockToSelect.clientId },
};
}
case 'TOGGLE_SELECTION':
return {
...BLOCK_SELECTION_INITIAL_STATE,
isEnabled: action.isSelectionEnabled,
};
case 'SELECTION_CHANGE':
return {
...BLOCK_SELECTION_INITIAL_STATE,
start: {
clientId: action.clientId,
attributeKey: action.attributeKey,
Expand All @@ -1038,6 +1004,51 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
offset: action.endOffset,
},
};
case 'RESET_BLOCKS': {
const {
selectionStart: start = {},
selectionEnd: end = {},
} = action;

return { start, end };
}
}

return state;
}

/**
* Reducer returning whether the user is multi-selecting.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
export function isMultiSelecting( state = false, action ) {
switch ( action.type ) {
case 'START_MULTI_SELECT':
return true;

case 'STOP_MULTI_SELECT':
return false;
}

return state;
}

/**
* Reducer returning whether selection is enabled.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
export function isSelectionEnabled( state = true, action ) {
switch ( action.type ) {
case 'TOGGLE_SELECTION':
return action.isSelectionEnabled;
}

return state;
Expand Down Expand Up @@ -1228,6 +1239,8 @@ export default combineReducers( {
isTyping,
isCaretWithinFormattedText,
blockSelection,
isMultiSelecting,
isSelectionEnabled,
blocksMode,
blockListSettings,
insertionPoint,
Expand Down
4 changes: 2 additions & 2 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ export function hasMultiSelection( state ) {
* @return {boolean} True if multi-selecting, false if not.
*/
export function isMultiSelecting( state ) {
return state.blockSelection.isMultiSelecting;
return state.isMultiSelecting;
}

/**
Expand All @@ -886,7 +886,7 @@ export function isMultiSelecting( state ) {
* @return {boolean} True if it should be possible to multi-select blocks, false if multi-selection is disabled.
*/
export function isSelectionEnabled( state ) {
return state.blockSelection.isEnabled;
return state.isSelectionEnabled;
}

/**
Expand Down
Loading

0 comments on commit ee24ec0

Please sign in to comment.