Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide the "Continue writing" prompt if the last block is an empty text block #1502

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 66 additions & 24 deletions editor/modes/visual-editor/block-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import { ENTER } from 'utils/keycodes';
import VisualEditorBlock from './block';
import {
getBlockUids,
getBlock,
getBlockInsertionPoint,
isBlockInsertionPointVisible,
hasTypedInSelectedBlock,
getMultiSelectedBlocksStartUid,
getMultiSelectedBlocksEndUid,
getMultiSelectedBlocks,
Expand Down Expand Up @@ -192,19 +194,33 @@ class VisualEditorBlockList extends Component {
}

render() {
const { blocks, showInsertionPoint, insertionPoint, multiSelectedBlockUids } = this.props;
const insertionPointIndex = blocks.indexOf( insertionPoint );
const {
blockUids,
lastBlock,
hasTypedInLastBlock,
showInsertionPoint,
insertionPoint,
multiSelectedBlockUids,
} = this.props;
const insertionPointIndex = blockUids.indexOf( insertionPoint );
const blocksWithInsertionPoint = showInsertionPoint
? [
...blocks.slice( 0, insertionPointIndex + 1 ),
...blockUids.slice( 0, insertionPointIndex + 1 ),
INSERTION_POINT_PLACEHOLDER,
...blocks.slice( insertionPointIndex + 1 ),
...blockUids.slice( insertionPointIndex + 1 ),
]
: blocks;
: blockUids;

const showContinueWriting = (
! lastBlock ||
lastBlock.name !== getDefaultBlock() ||
!! lastBlock.attributes.content ||
hasTypedInLastBlock
);

return (
<div>
{ !! blocks.length && blocksWithInsertionPoint.map( ( uid ) => {
{ !! blockUids.length && blocksWithInsertionPoint.map( ( uid ) => {
if ( uid === INSERTION_POINT_PLACEHOLDER ) {
return (
<div
Expand All @@ -225,30 +241,56 @@ class VisualEditorBlockList extends Component {
);
} ) }

<input
type="text"
readOnly
className="editor-visual-editor__placeholder"
value={ ! blocks.length ? __( 'Write your story' ) : __( 'Continue writing…' ) }
onFocus={ ! blocks.length ? this.appendDefaultBlock : noop }
onClick={ !! blocks.length ? this.appendDefaultBlock : noop }
onKeyDown={ !! blocks.length ? this.onPlaceholderKeyDown : noop }
/>
{ showContinueWriting && (
<input
type="text"
readOnly
className="editor-visual-editor__placeholder"
value={ ! blockUids.length
? __( 'Write your story' )
: __( 'Continue writing…' )
}
onFocus={ ! blockUids.length
? this.appendDefaultBlock
: noop
}
onClick={ !! blockUids.length
? this.appendDefaultBlock
: noop
}
onKeyDown={ !! blockUids.length
? this.onPlaceholderKeyDown
: noop
}
/>
) }
</div>
);
}
}

export default connect(
( state ) => ( {
blocks: getBlockUids( state ),
insertionPoint: getBlockInsertionPoint( state ),
showInsertionPoint: isBlockInsertionPointVisible( state ),
selectionStart: getMultiSelectedBlocksStartUid( state ),
selectionEnd: getMultiSelectedBlocksEndUid( state ),
multiSelectedBlocks: getMultiSelectedBlocks( state ),
multiSelectedBlockUids: getMultiSelectedBlockUids( state ),
} ),
( state ) => {
const blockUids = getBlockUids( state );
const lastBlockUid = blockUids.length
? blockUids[ blockUids.length - 1 ]
: null;
return {
blockUids,
lastBlock: lastBlockUid
? getBlock( state, lastBlockUid )
: null,
hasTypedInLastBlock: lastBlockUid
? hasTypedInSelectedBlock( state, lastBlockUid )
: null,
insertionPoint: getBlockInsertionPoint( state ),
showInsertionPoint: isBlockInsertionPointVisible( state ),
selectionStart: getMultiSelectedBlocksStartUid( state ),
selectionEnd: getMultiSelectedBlocksEndUid( state ),
multiSelectedBlocks: getMultiSelectedBlocks( state ),
multiSelectedBlockUids: getMultiSelectedBlockUids( state ),
};
},
( dispatch ) => ( {
onInsertBlock( block ) {
dispatch( insertBlock( block ) );
Expand Down
16 changes: 16 additions & 0 deletions editor/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,22 @@ export function isTypingInBlock( state, uid ) {
return state.selectedBlock.typing;
}

/**
* Returns true if the block corresponding to the specified unique ID is
* selected and the user has typed within it before, or false otherwise.
*
* @param {Object} state Global application state
* @param {Object} uid Block unique ID
* @return {Boolean} Whether user is typing within block
*/
export function hasTypedInSelectedBlock( state, uid ) {
if ( ! isBlockSelected( state, uid ) ) {
return false;
}

return state.selectedBlock.hasTypedBefore;
}

/**
* Returns the unique ID of the block after which a new block insertion would
* be placed, or null if the insertion point is not shown. Defaults to the
Expand Down
2 changes: 2 additions & 0 deletions editor/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,15 @@ export function selectedBlock( state = {}, action ) {
return {
uid: action.uid,
typing: true,
hasTypedBefore: true,
focus: {},
};
}

return {
...state,
typing: true,
hasTypedBefore: true,
};

case 'STOP_TYPING':
Expand Down
27 changes: 23 additions & 4 deletions editor/test/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,12 @@ describe( 'state', () => {
uid: 'chicken',
} );

expect( state ).to.eql( { uid: 'chicken', typing: true, focus: {} } );
expect( state ).to.eql( {
uid: 'chicken',
typing: true,
hasTypedBefore: true,
focus: {},
} );
} );

it( 'should do nothing if typing stopped not within selected block', () => {
Expand All @@ -823,17 +828,31 @@ describe( 'state', () => {
uid: 'chicken',
} );

expect( state ).to.eql( { uid: 'chicken', typing: false, focus: {} } );
expect( state ).to.eql( {
uid: 'chicken',
typing: false,
hasTypedBefore: true,
focus: {},
} );
} );

it( 'should set the typing flag and merge the existing state', () => {
const original = deepFreeze( { uid: 'ribs', typing: false, focus: { editable: 'citation' } } );
const original = deepFreeze( {
uid: 'ribs',
typing: false,
focus: { editable: 'citation' },
} );
const state = selectedBlock( original, {
type: 'START_TYPING',
uid: 'ribs',
} );

expect( state ).to.eql( { uid: 'ribs', typing: true, focus: { editable: 'citation' } } );
expect( state ).to.eql( {
uid: 'ribs',
typing: true,
hasTypedBefore: true,
focus: { editable: 'citation' },
} );
} );

it( 'should replace the selected block', () => {
Expand Down