Skip to content

Commit

Permalink
Move the post title selection state to the store and update PostTitle (
Browse files Browse the repository at this point in the history
…#16704)

* Move the post title selection state to the store and update PostTitle

* Fix jsdoc type returned for postTitle reducer

* Update native version of VisualEditor to use the store to know if the post title is selected

* Update doc

* Remove unused clearSelectedBlock props in PostTitle web and bring back focus in native version

* Fork core/editor store for native instead of modifying it

* Move tests to native

* Update docs

* Revert changes to web PostTitle

* Fix post title blur on block selection

* Update the isPostTitleSelected state if any other block is selected
  • Loading branch information
Tug authored Jul 25, 2019
1 parent bd4c495 commit dd34d32
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 53 deletions.
37 changes: 3 additions & 34 deletions packages/edit-post/src/components/visual-editor/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,6 @@ import { ReadableContentView } from '@wordpress/components';
import styles from './style.scss';

class VisualEditor extends Component {
constructor() {
super( ...arguments );

this.onPostTitleSelect = this.onPostTitleSelect.bind( this );
this.onPostTitleUnselect = this.onPostTitleUnselect.bind( this );

this.state = {
isPostTitleSelected: false,
};
}

static getDerivedStateFromProps( props ) {
if ( props.isAnyBlockSelected ) {
return { isPostTitleSelected: false };
}
return null;
}

onPostTitleSelect() {
this.setState( { isPostTitleSelected: true } );
this.props.clearSelectedBlock();
}

onPostTitleUnselect() {
this.setState( { isPostTitleSelected: false } );
}

renderHeader() {
const {
editTitle,
Expand All @@ -55,9 +28,6 @@ class VisualEditor extends Component {
innerRef={ setTitleRef }
title={ title }
onUpdate={ editTitle }
onSelect={ this.onPostTitleSelect }
onUnselect={ this.onPostTitleUnselect }
isSelected={ this.state.isPostTitleSelected }
placeholder={ __( 'Add title' ) }
borderStyle={
this.props.isFullyBordered ?
Expand Down Expand Up @@ -93,7 +63,7 @@ class VisualEditor extends Component {
isFullyBordered={ isFullyBordered }
rootViewHeight={ rootViewHeight }
safeAreaBottomInset={ safeAreaBottomInset }
isPostTitleSelected={ this.state.isPostTitleSelected }
isPostTitleSelected={ this.props.isPostTitleSelected }
onBlockTypeSelected={ this.onPostTitleUnselect }
/>
</BlockEditorProvider>
Expand All @@ -106,14 +76,13 @@ export default compose( [
const {
getEditorBlocks,
getEditedPostAttribute,
isPostTitleSelected,
} = select( 'core/editor' );

const { getSelectedBlockClientId } = select( 'core/block-editor' );

return {
blocks: getEditorBlocks(),
title: getEditedPostAttribute( 'title' ),
isAnyBlockSelected: !! getSelectedBlockClientId(),
isPostTitleSelected: isPostTitleSelected(),
};
} ),
withDispatch( ( dispatch ) => {
Expand Down
64 changes: 45 additions & 19 deletions packages/editor/src/components/post-title/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { isEmpty } from 'lodash';
import { Component } from '@wordpress/element';
import { RichText } from '@wordpress/rich-text';
import { decodeEntities } from '@wordpress/html-entities';
import { withDispatch } from '@wordpress/data';
import { withDispatch, withSelect } from '@wordpress/data';
import { withFocusOutside } from '@wordpress/components';
import { withInstanceId, compose } from '@wordpress/compose';
import { __, sprintf } from '@wordpress/i18n';
Expand All @@ -22,6 +22,13 @@ import { pasteHandler } from '@wordpress/blocks';
import styles from './style.scss';

class PostTitle extends Component {
componentDidUpdate( prevProps ) {
// Unselect if any other block is selected
if ( this.props.isSelected && ! prevProps.isAnyBlockSelected && this.props.isAnyBlockSelected ) {
this.props.onUnselect();
}
}

componentDidMount() {
if ( this.props.innerRef ) {
this.props.innerRef( this );
Expand Down Expand Up @@ -91,27 +98,46 @@ class PostTitle extends Component {
}
}

const applyWithDispatch = withDispatch( ( dispatch ) => {
const {
undo,
redo,
} = dispatch( 'core/editor' );
export default compose(
withSelect( ( select ) => {
const {
isPostTitleSelected,
} = select( 'core/editor' );

const {
insertDefaultBlock,
} = dispatch( 'core/block-editor' );
const { getSelectedBlockClientId } = select( 'core/block-editor' );

return {
onEnterPress() {
insertDefaultBlock( undefined, undefined, 0 );
},
onUndo: undo,
onRedo: redo,
};
} );
return {
isAnyBlockSelected: !! getSelectedBlockClientId(),
isSelected: isPostTitleSelected(),
};
} ),
withDispatch( ( dispatch ) => {
const {
undo,
redo,
togglePostTitleSelection,
} = dispatch( 'core/editor' );

export default compose(
applyWithDispatch,
const {
clearSelectedBlock,
insertDefaultBlock,
} = dispatch( 'core/block-editor' );

return {
onEnterPress() {
insertDefaultBlock( undefined, undefined, 0 );
},
onUndo: undo,
onRedo: redo,
onSelect() {
togglePostTitleSelection( true );
clearSelectedBlock();
},
onUnselect() {
togglePostTitleSelection( false );
},
};
} ),
withInstanceId,
withFocusOutside
)( PostTitle );
16 changes: 16 additions & 0 deletions packages/editor/src/store/actions.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

export * from './actions.js';

/**
* Returns an action object that enables or disables post title selection.
*
* @param {boolean} [isSelected=true] Whether post title is currently selected.
* @return {Object} Action object.
*/
export function togglePostTitleSelection( isSelected = true ) {
return {
type: 'TOGGLE_POST_TITLE_SELECTION',
isSelected,
};
}
64 changes: 64 additions & 0 deletions packages/editor/src/store/reducer.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* External dependencies
*/
import optimist from 'redux-optimist';

/**
* WordPress dependencies
*/
import { combineReducers } from '@wordpress/data';

/**
* Internal dependencies
*/
import {
editor,
initialEdits,
currentPost,
preferences,
saving,
postLock,
reusableBlocks,
template,
previewLink,
postSavingLock,
isReady,
editorSettings,
} from './reducer.js';

export * from './reducer.js';

/**
* Reducer returning the post title state.
*
* @param {PostTitleState} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
export const postTitle = combineReducers( {
isSelected( state = false, action ) {
switch ( action.type ) {
case 'TOGGLE_POST_TITLE_SELECTION':
return action.isSelected;
}

return state;
},
} );

export default optimist( combineReducers( {
editor,
initialEdits,
currentPost,
preferences,
saving,
postLock,
reusableBlocks,
template,
previewLink,
postSavingLock,
isReady,
editorSettings,
postTitle,
} ) );
13 changes: 13 additions & 0 deletions packages/editor/src/store/selectors.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

export * from './selectors.js';

/**
* Returns true if post title is selected.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether current post title is selected.
*/
export function isPostTitleSelected( state ) {
return state.postTitle.isSelected;
}
17 changes: 17 additions & 0 deletions packages/editor/src/store/test/actions.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

/**
* Internal dependencies
*/
import { togglePostTitleSelection } from '../actions';

describe( 'Editor actions', () => {
describe( 'togglePostTitleSelection', () => {
it( 'should return the TOGGLE_POST_TITLE_SELECTION action', () => {
const result = togglePostTitleSelection( true );
expect( result ).toEqual( {
type: 'TOGGLE_POST_TITLE_SELECTION',
isSelected: true,
} );
} );
} );
} );
34 changes: 34 additions & 0 deletions packages/editor/src/store/test/reducer.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Internal dependencies
*/
import {
postTitle,
} from '../reducer';

describe( 'state native', () => {
describe( 'postTitle', () => {
describe( 'isSelected()', () => {
it( 'should not be selected by default', () => {
expect( postTitle( undefined, {} ).isSelected ).toBe( false );
} );

it( 'should return false if not selecting the post title', () => {
const action = {
type: 'TOGGLE_POST_TITLE_SELECTION',
isSelected: false,
};

expect( postTitle( { isSelected: true }, action ).isSelected ).toBe( false );
} );

it( 'should return true if selecting the post title', () => {
const action = {
type: 'TOGGLE_POST_TITLE_SELECTION',
isSelected: true,
};

expect( postTitle( { isSelected: false }, action ).isSelected ).toBe( true );
} );
} );
} );
} );
28 changes: 28 additions & 0 deletions packages/editor/src/store/test/selectors.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Internal dependencies
*/
import { isPostTitleSelected } from '../selectors';

describe( 'selectors native', () => {
describe( 'isPostTitleSelected', () => {
it( 'should return true if the post title is selected', () => {
const state = {
postTitle: {
isSelected: true,
},
};

expect( isPostTitleSelected( state ) ).toBe( true );
} );

it( 'should return false if the post title is not selected', () => {
const state = {
postTitle: {
isSelected: false,
},
};

expect( isPostTitleSelected( state ) ).toBe( false );
} );
} );
} );

0 comments on commit dd34d32

Please sign in to comment.