Skip to content

Commit

Permalink
Refactor BlockToolbar out of BlockList (#16677)
Browse files Browse the repository at this point in the history
* Move BlockToolbar from BlockList to Layout

* Remove BlockEditorProvider from BlockList and add native version of EditorProvider to Editor. Plus support InsertionPoint and BlockListAppender

* Revert BlockListAppender and InsertionPoint additions

* Fix dismissing block picker

* Add missing function in BlockList

* Disable add block in HTML mode and show hide keyboard button only when keyboard is shown

* Fix bringing back finishInsertingOrReplacingBlock

* Fix inserting block in first position when post title is selected

* Show insertion point before block if its replaceable

* Fix missing shouldPreventAutomaticScroll props for iOS

* Fix native tests

* Add back bottom View to push block list up

* Improve defining toolbar height

* Make html view a flexbax

* Quickly hide the modal to let the keyboard show up after inserting a new text based block

* Let's unmount the modal instead to make sure we don't have timing errors

* revert to defining the toolbar height in the component itsef

* Revert "Make html view a flexbax"

This reverts commit 59f0431.

* Simplify layout

* Fix dismiss keyboard on iOS
  • Loading branch information
Tug authored and gziolo committed Aug 29, 2019
1 parent 8d5b215 commit 1629241
Show file tree
Hide file tree
Showing 26 changed files with 920 additions and 486 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ class BlockListBlock extends Component {
const accessibilityLabel = this.getAccessibilityLabel();

return (
// accessible prop needs to be false to access children
// https://facebook.github.io/react-native/docs/accessibility#accessible-ios-android
<TouchableWithoutFeedback
onPress={ this.onFocus }
accessible={ ! isSelected }
Expand All @@ -138,7 +136,6 @@ class BlockListBlock extends Component {
</View>
{ isSelected && <BlockMobileToolbar clientId={ clientId } /> }
</View>

</TouchableWithoutFeedback>
);
}
Expand Down
149 changes: 26 additions & 123 deletions packages/block-editor/src/components/block-list/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,26 @@
* External dependencies
*/
import { identity } from 'lodash';
import { Text, View, Keyboard, SafeAreaView, Platform, TouchableWithoutFeedback } from 'react-native';
import { subscribeMediaAppend } from 'react-native-gutenberg-bridge';
import { Text, View, Platform, TouchableWithoutFeedback } from 'react-native';

/**
* WordPress dependencies
*/
import { Component, Fragment } from '@wordpress/element';
import { Component } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { createBlock, isUnmodifiedDefaultBlock } from '@wordpress/blocks';
import { HTMLTextInput, KeyboardAvoidingView, KeyboardAwareFlatList, ReadableContentView } from '@wordpress/components';
import { KeyboardAwareFlatList, ReadableContentView } from '@wordpress/components';

/**
* Internal dependencies
*/
import styles from './style.scss';
import BlockListBlock from './block';
import BlockToolbar from '../block-toolbar';
import DefaultBlockAppender from '../default-block-appender';
import Inserter from '../inserter';

const blockMobileToolbarHeight = 44;
const toolbarHeight = 44;
const innerToolbarHeight = 44;

export class BlockList extends Component {
constructor() {
Expand All @@ -34,34 +30,11 @@ export class BlockList extends Component {
this.renderItem = this.renderItem.bind( this );
this.renderAddBlockSeparator = this.renderAddBlockSeparator.bind( this );
this.renderBlockListFooter = this.renderBlockListFooter.bind( this );
this.shouldFlatListPreventAutomaticScroll = this.shouldFlatListPreventAutomaticScroll.bind( this );
this.renderDefaultBlockAppender = this.renderDefaultBlockAppender.bind( this );
this.onBlockTypeSelected = this.onBlockTypeSelected.bind( this );
this.keyboardDidShow = this.keyboardDidShow.bind( this );
this.keyboardDidHide = this.keyboardDidHide.bind( this );
this.onCaretVerticalPositionChange = this.onCaretVerticalPositionChange.bind( this );
this.scrollViewInnerRef = this.scrollViewInnerRef.bind( this );
this.getNewBlockInsertionIndex = this.getNewBlockInsertionIndex.bind( this );

this.state = {
blockTypePickerVisible: false,
isKeyboardVisible: false,
};
}

// TODO: in the near future this will likely be changed to onShowBlockTypePicker and bound to this.props
// once we move the action to the toolbar
showBlockTypePicker( show ) {
this.setState( { blockTypePickerVisible: show } );
}

onBlockTypeSelected( itemValue ) {
this.setState( { blockTypePickerVisible: false } );

// create an empty block of the selected type
const newBlock = createBlock( itemValue );

this.finishBlockAppendingOrReplacing( newBlock );
this.shouldFlatListPreventAutomaticScroll = this.shouldFlatListPreventAutomaticScroll.bind( this );
}

finishBlockAppendingOrReplacing( newBlock ) {
Expand All @@ -88,48 +61,7 @@ export class BlockList extends Component {
}

blockHolderBorderStyle() {
return this.state.isFullyBordered ? styles.blockHolderFullBordered : styles.blockHolderSemiBordered;
}

componentDidMount() {
this._isMounted = true;
Keyboard.addListener( 'keyboardDidShow', this.keyboardDidShow );
Keyboard.addListener( 'keyboardDidHide', this.keyboardDidHide );

this.subscriptionParentMediaAppend = subscribeMediaAppend( ( payload ) => {
// create an empty media block
const newMediaBlock = createBlock( 'core/' + payload.mediaType );

// now set the url and id
if ( payload.mediaType === 'image' ) {
newMediaBlock.attributes.url = payload.mediaUrl;
} else if ( payload.mediaType === 'video' ) {
newMediaBlock.attributes.src = payload.mediaUrl;
}

newMediaBlock.attributes.id = payload.mediaId;

// finally append or replace as appropriate
this.finishBlockAppendingOrReplacing( newMediaBlock );
} );
}

componentWillUnmount() {
Keyboard.removeListener( 'keyboardDidShow', this.keyboardDidShow );
Keyboard.removeListener( 'keyboardDidHide', this.keyboardDidHide );

if ( this.subscriptionParentMediaAppend ) {
this.subscriptionParentMediaAppend.remove();
}
this._isMounted = false;
}

keyboardDidShow() {
this.setState( { isKeyboardVisible: true } );
}

keyboardDidHide() {
this.setState( { isKeyboardVisible: false } );
return this.props.isFullyBordered ? styles.blockHolderFullBordered : styles.blockHolderSemiBordered;
}

onCaretVerticalPositionChange( targetId, caretY, previousCaretY ) {
Expand All @@ -141,7 +73,7 @@ export class BlockList extends Component {
}

shouldFlatListPreventAutomaticScroll() {
return this.state.blockTypePickerVisible;
return this.props.isBlockInsertionPointVisible;
}

renderDefaultBlockAppender() {
Expand All @@ -159,7 +91,7 @@ export class BlockList extends Component {
);
}

renderList() {
render() {
return (
<View
style={ { flex: 1 } }
Expand All @@ -169,10 +101,7 @@ export class BlockList extends Component {
{ ...( Platform.OS === 'android' ? { removeClippedSubviews: false } : {} ) } // Disable clipping on Android to fix focus losing. See https://github.com/wordpress-mobile/gutenberg-mobile/pull/741#issuecomment-472746541
accessibilityLabel="block-list"
innerRef={ this.scrollViewInnerRef }
blockToolbarHeight={ toolbarHeight }
innerToolbarHeight={ blockMobileToolbarHeight }
safeAreaBottomInset={ this.props.safeAreaBottomInset }
parentHeight={ this.props.rootViewHeight }
extraScrollHeight={ innerToolbarHeight + 10 }
keyboardShouldPersistTaps="always"
style={ styles.list }
data={ this.props.blockClientIds }
Expand All @@ -185,53 +114,21 @@ export class BlockList extends Component {
ListEmptyComponent={ this.renderDefaultBlockAppender }
ListFooterComponent={ this.renderBlockListFooter }
/>
<SafeAreaView>
<View style={ { height: toolbarHeight } } />
</SafeAreaView>
<KeyboardAvoidingView
style={ styles.blockToolbarKeyboardAvoidingView }
parentHeight={ this.props.rootViewHeight }
>
<BlockToolbar
onInsertClick={ () => {
this.showBlockTypePicker( true );
} }
showKeyboardHideButton={ this.state.isKeyboardVisible }
/>
</KeyboardAvoidingView>
</View>
);
}

render() {
return (
<Fragment>
{ this.renderList() }
{ this.state.blockTypePickerVisible && (
<Inserter
onDismiss={ () => this.showBlockTypePicker( false ) }
onValueSelected={ this.onBlockTypeSelected }
isReplacement={ this.isReplaceable( this.props.selectedBlock ) }
addExtraBottomPadding={ this.props.safeAreaBottomInset === 0 }
/>
) }
</Fragment>
);
}

isReplaceable( block ) {
if ( ! block ) {
return false;
}
return isUnmodifiedDefaultBlock( block );
}

renderItem( { item: clientId, index } ) {
const shouldShowAddBlockSeparator = this.state.blockTypePickerVisible && ( this.props.isBlockSelected( clientId ) || ( index === 0 && this.props.isPostTitleSelected ) );
const shouldPutAddBlockSeparatorAboveBlock = this.isReplaceable( this.props.selectedBlock ) || this.props.isPostTitleSelected;

renderItem( { item: clientId } ) {
return (
<ReadableContentView reversed={ shouldPutAddBlockSeparatorAboveBlock }>
<ReadableContentView>
{ this.props.shouldShowInsertionPoint( clientId ) && this.renderAddBlockSeparator() }
<BlockListBlock
key={ clientId }
showTitle={ false }
Expand All @@ -241,7 +138,6 @@ export class BlockList extends Component {
borderStyle={ this.blockHolderBorderStyle() }
focusedBorderColor={ styles.blockHolderFocused.borderColor }
/>
{ shouldShowAddBlockSeparator && this.renderAddBlockSeparator() }
</ReadableContentView>
);
}
Expand All @@ -266,12 +162,6 @@ export class BlockList extends Component {
</TouchableWithoutFeedback>
);
}

renderHTML() {
return (
<HTMLTextInput { ...this.props } parentHeight={ this.props.rootViewHeight } />
);
}
}

export default compose( [
Expand All @@ -284,15 +174,28 @@ export default compose( [
getSelectedBlock,
getSelectedBlockClientId,
isBlockSelected,
getBlockInsertionPoint,
isBlockInsertionPointVisible,
} = select( 'core/block-editor' );

const selectedBlockClientId = getSelectedBlockClientId();
const blockClientIds = getBlockOrder( rootClientId );
const insertionPoint = getBlockInsertionPoint();
const shouldShowInsertionPoint = ( clientId ) => {
return (
isBlockInsertionPointVisible() &&
insertionPoint.rootClientId === rootClientId &&
blockClientIds[ insertionPoint.index ] === clientId
);
};

return {
blockClientIds: getBlockOrder( rootClientId ),
blockClientIds,
blockCount: getBlockCount( rootClientId ),
getBlockName,
isBlockSelected,
isBlockInsertionPointVisible: isBlockInsertionPointVisible(),
shouldShowInsertionPoint,
selectedBlock: getSelectedBlock(),
selectedBlockClientId,
selectedBlockOrder: getBlockIndex( selectedBlockClientId ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@
background-color: $white;
}

.blockToolbarKeyboardAvoidingView {
position: absolute;
bottom: 0;
right: 0;
left: 0;
}

.blockHolderSemiBordered {
border-top-width: 1px;
border-bottom-width: 1px;
Expand All @@ -61,7 +54,6 @@
border-right-width: 1px;
}


.blockContainerFocused {
background-color: $white;
padding-left: 16;
Expand Down
Loading

0 comments on commit 1629241

Please sign in to comment.