Skip to content

Commit

Permalink
[RNMobile] Block title in unsupported block (#18268)
Browse files Browse the repository at this point in the history
* WC: #479: Adding help icon and modal to unsupported block. Also putting original name in place of 'Unsupported'.

* WC: #479: Adding in unit tests for the component.

* WC: #479: Changing the help icon press surface to the whole block because the small icon was too hard to press. Also rearranging the BottomSheet to work the height paddings out correctly.

* WC: #479: Changing accessibility label and adding comment.

* WC: #479: Adding in text/buttons to match later design.

* WC: issue #479: Changing only the question mark icon to be tappable for the help block. Few color changes. Adding some text to the help block.

* Display 'unsupported' on all unsupported blocks on mobile

* Update the test snapshot of Unsupported block on mobile

* Need to mock styling on mobile

* Adjust tests to latest changes

* Display the block name in quotes, for clarity

* Dark mode of info text, title and description

* sprintf to compose string, separate strings per platform

* Wrap JSX in the grouping operator, as usual

* Remove dismiss button, not used in other bottom-sheets

* Remove unused import

* Revise sprintf format to green the linter

* Update tests after removing the Close button

* Wrap more JSX in the grouping operator, as usual

* Adjust the info-icon color

* Different colors for the icon on the sheet

* Remove local mock, using the global styleMock.js instead

* Enable testing both mobile platforms
  • Loading branch information
hypest committed Nov 8, 2019
1 parent a71241c commit 79636ce
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 6 deletions.
79 changes: 74 additions & 5 deletions packages/block-library/src/missing/edit.native.js
@@ -1,43 +1,112 @@
/**
* External dependencies
*/
import { View, Text } from 'react-native';
import { Platform, View, Text, TouchableWithoutFeedback } from 'react-native';

/**
* WordPress dependencies
*/
import { Icon } from '@wordpress/components';
import { BottomSheet, Icon } from '@wordpress/components';
import { withPreferredColorScheme } from '@wordpress/compose';
import { coreBlocks } from '@wordpress/block-library';
import { normalizeIconObject } from '@wordpress/blocks';
import { Component } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import styles from './style.scss';

export class UnsupportedBlockEdit extends Component {
constructor( props ) {
super( props );
this.state = { showHelp: false };
}

toggleSheet() {
this.setState( {
showHelp: ! this.state.showHelp,
} );
}

renderHelpIcon() {
const infoIconStyle = this.props.getStylesFromColorScheme( styles.infoIcon, styles.infoIconDark );

return (
<TouchableWithoutFeedback
accessibilityLabel={ __( 'Help icon' ) }
accessibilityRole={ 'button' }
accessibilityHint={ __( 'Tap here to show help' ) }
onPress={ this.toggleSheet.bind( this ) }
>
<View style={ styles.helpIconContainer } >
<Icon
className="unsupported-icon-help"
label={ __( 'Help icon' ) }
icon="editor-help"
color={ infoIconStyle.color }
/>
</View>
</TouchableWithoutFeedback>
);
}

renderSheet( title ) {
const { getStylesFromColorScheme } = this.props;
const infoTextStyle = getStylesFromColorScheme( styles.infoText, styles.infoTextDark );
const infoTitleStyle = getStylesFromColorScheme( styles.infoTitle, styles.infoTitleDark );
const infoDescriptionStyle = getStylesFromColorScheme( styles.infoDescription, styles.infoDescriptionDark );
const infoSheetIconStyle = getStylesFromColorScheme( styles.infoSheetIcon, styles.infoSheetIconDark );

// translators: %s: Name of the block
const titleFormat = Platform.OS === 'android' ? __( '\'%s\' isn\'t yet supported on WordPress for Android' ) :
__( '\'%s\' isn\'t yet supported on WordPress for iOS' );
const infoTitle = sprintf(
titleFormat,
title,
);

return (
<BottomSheet
isVisible={ this.state.showHelp }
hideHeader
onClose={ this.toggleSheet.bind( this ) }
>
<View style={ styles.infoContainer } >
<Icon icon="editor-help" color={ infoSheetIconStyle.color } size={ styles.infoSheetIcon.size } />
<Text style={ [ infoTextStyle, infoTitleStyle ] }>
{ infoTitle }
</Text>
<Text style={ [ infoTextStyle, infoDescriptionStyle ] }>
{ __( 'We are working hard to add more blocks with each release. In the meantime, you can also edit this post on the web.' ) }
</Text>
</View>
</BottomSheet>
);
}

render() {
const { originalName } = this.props.attributes;
const { getStylesFromColorScheme, preferredColorScheme } = this.props;
const blockType = coreBlocks[ originalName ];

const title = blockType ? blockType.settings.title : __( 'Unsupported' );
const title = blockType ? blockType.settings.title : originalName;
const titleStyle = getStylesFromColorScheme( styles.unsupportedBlockMessage, styles.unsupportedBlockMessageDark );

const subTitleStyle = getStylesFromColorScheme( styles.unsupportedBlockSubtitle, styles.unsupportedBlockSubtitleDark );
const subtitle = blockType ? <Text style={ subTitleStyle }>{ __( 'Unsupported' ) }</Text> : null;
const subtitle = <Text style={ subTitleStyle }>{ __( 'Unsupported' ) }</Text>;

const icon = blockType ? normalizeIconObject( blockType.settings.icon ) : 'admin-plugins';
const iconStyle = getStylesFromColorScheme( styles.unsupportedBlockIcon, styles.unsupportedBlockIconDark );
const iconClassName = 'unsupported-icon' + '-' + preferredColorScheme;
return (
<View style={ getStylesFromColorScheme( styles.unsupportedBlock, styles.unsupportedBlockDark ) }>
{ this.renderHelpIcon() }
<Icon className={ iconClassName } icon={ icon && icon.src ? icon.src : icon } color={ iconStyle.color } />
<Text style={ titleStyle }>{ title }</Text>
{ subtitle }
{ this.renderSheet( title ) }
</View>
);
}
Expand Down
83 changes: 82 additions & 1 deletion packages/block-library/src/missing/style.native.scss
@@ -1,7 +1,88 @@
/** @format */
.content {
padding-top: 8;
padding-bottom: 0;
padding-left: 24;
padding-right: 24;
align-items: center;
justify-content: space-evenly;
}

.helpIconContainer {
position: absolute;
top: 0;
right: 0;
height: 48;
width: 48;
padding-top: 12;
padding-right: 12;
justify-content: flex-start;
align-items: flex-end;
}

.infoContainer {
flex-direction: column;
align-items: center;
justify-content: flex-end;
}

.infoIcon {
size: 36;
height: 36;
padding-top: 8;
padding-bottom: 8;
color: $gray-darken-20;
}

.infoIconDark {
color: $gray-20;
}

.infoSheetIcon {
size: 36;
height: 36;
padding-top: 8;
padding-bottom: 8;
color: $gray;
}

.infoSheetIconDark {
color: $gray-20;
}

.infoText {
text-align: center;
color: $gray-dark;
}

.infoTextDark {
color: $white;
}

.infoTitle {
padding-top: 8;
padding-bottom: 12;
font-size: 20;
font-weight: bold;
color: $gray-dark;
}

.infoTitleDark {
color: $white;
}

.infoDescription {
padding-bottom: 24;
font-size: 16;
color: $gray-darken-20;
}

.infoDescriptionDark {
color: $gray-20;
}

.unsupportedBlock {
background-color: #e9eff3; // grey lighten 30
background-color: $gray-lighten-30;
padding-top: 24;
padding-bottom: 24;
padding-left: 8;
Expand Down
@@ -0,0 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Missing block renders without crashing 1`] = `
<View>
<View
accessibilityHint="Tap here to show help"
accessibilityLabel="Help icon"
accessibilityRole="button"
accessible={true}
clickable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
>
Svg
</View>
Svg
<Text>
missing/block/title
</Text>
<Text>
Unsupported
</Text>
Modal
</View>
`;
77 changes: 77 additions & 0 deletions packages/block-library/src/missing/test/edit.native.js
@@ -0,0 +1,77 @@
/**
* External dependencies
*/
import renderer from 'react-test-renderer';
import { Text, Platform } from 'react-native';

/**
* WordPress dependencies
*/
import { BottomSheet, Icon } from '@wordpress/components';
jest.mock( '@wordpress/blocks' );

/**
* Internal dependencies
*/
import UnsupportedBlockEdit from '../edit.native.js';

const defaultAttributes = {
originalName: 'missing/block/title',
};

const getTestComponentWithContent = ( attributes = defaultAttributes ) => {
return renderer.create( <UnsupportedBlockEdit attributes={ attributes } /> );
};

describe( 'Missing block', () => {
it( 'renders without crashing', () => {
const component = getTestComponentWithContent();
const rendered = component.toJSON();
expect( rendered ).toMatchSnapshot();
} );

describe( 'help modal', () => {
it( 'renders help icon', () => {
const component = getTestComponentWithContent();
const testInstance = component.root;
const icons = testInstance.findAllByType( Icon );
expect( icons.length ).toBe( 2 );
expect( icons[ 0 ].props.icon ).toBe( 'editor-help' );
} );

it( 'renders info icon on modal', () => {
const component = getTestComponentWithContent();
const testInstance = component.root;
const bottomSheet = testInstance.findByType( BottomSheet );
const children = bottomSheet.props.children.props.children;
expect( children.length ).toBe( 3 ); // 4 children in the bottom sheet: the icon, the "isn't yet supported" title and the "We are working hard..." message
expect( children[ 0 ].props.icon ).toBe( 'editor-help' );
} );

it( 'renders unsupported text on modal', () => {
const component = getTestComponentWithContent();
const testInstance = component.root;
const bottomSheet = testInstance.findByType( BottomSheet );
const children = bottomSheet.props.children.props.children;
const expectedOSString = Platform.OS === 'ios' ? 'iOS' : 'Android';
expect( children[ 1 ].props.children ).toBe( '\'' + defaultAttributes.originalName + '\' isn\'t yet supported on WordPress for ' + expectedOSString );
} );
} );

it( 'renders admin plugins icon', () => {
const component = getTestComponentWithContent();
const testInstance = component.root;
const icons = testInstance.findAllByType( Icon );
expect( icons.length ).toBe( 2 );
expect( icons[ 1 ].props.icon ).toBe( 'admin-plugins' );
} );

it( 'renders title text without crashing', () => {
const component = getTestComponentWithContent();
const testInstance = component.root;
const texts = testInstance.findAllByType( Text );
expect( texts.length ).toBe( 2 );
expect( texts[ 0 ].props.children ).toBe( 'missing/block/title' );
expect( texts[ 1 ].props.children ).toBe( 'Unsupported' );
} );
} );
6 changes: 6 additions & 0 deletions test/native/__mocks__/styleMock.js
Expand Up @@ -75,4 +75,10 @@ module.exports = {
unsupportedBlockIcon: {
color: 'white',
},
infoIcon: {
size: 36,
},
infoSheetIcon: {
color: 'gray',
},
};

0 comments on commit 79636ce

Please sign in to comment.