Skip to content

Commit

Permalink
Rnmobile/upload media failed state (#13615)
Browse files Browse the repository at this point in the history
*Implement upload media failed state
  • Loading branch information
marecar3 authored and youknowriad committed Mar 6, 2019
1 parent eedea1d commit 073ea83
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 61 deletions.
155 changes: 94 additions & 61 deletions packages/block-library/src/image/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@
* External dependencies
*/
import React from 'react';
import { View, Image, TextInput } from 'react-native';
import { View, ImageBackground, TextInput, Text, TouchableWithoutFeedback } from 'react-native';
import {
subscribeMediaUpload,
requestMediaPickFromMediaLibrary,
requestMediaPickFromDeviceLibrary,
requestMediaPickFromDeviceCamera,
mediaUploadSync,
requestImageFailedRetryDialog,
requestImageUploadCancelDialog,
} from 'react-native-gutenberg-bridge';

/**
* Internal dependencies
*/
import { MediaPlaceholder, RichText, BlockControls, InspectorControls } from '@wordpress/editor';
import { Toolbar, ToolbarButton, Spinner } from '@wordpress/components';
import { Toolbar, ToolbarButton, Spinner, Dashicon } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import ImageSize from './image-size';
import { isURL } from '@wordpress/url';
import styles from './styles.scss';

const MEDIA_ULOAD_STATE_UPLOADING = 1;
const MEDIA_ULOAD_STATE_SUCCEEDED = 2;
const MEDIA_ULOAD_STATE_FAILED = 3;
const MEDIA_UPLOAD_STATE_UPLOADING = 1;
const MEDIA_UPLOAD_STATE_SUCCEEDED = 2;
const MEDIA_UPLOAD_STATE_FAILED = 3;
const MEDIA_UPLOAD_STATE_RESET = 4;

export default class ImageEdit extends React.Component {
constructor( props ) {
Expand All @@ -31,13 +35,15 @@ export default class ImageEdit extends React.Component {
this.state = {
progress: 0,
isUploadInProgress: false,
isUploadFailed: false,
};

this.mediaUpload = this.mediaUpload.bind( this );
this.addMediaUploadListener = this.addMediaUploadListener.bind( this );
this.removeMediaUploadListener = this.removeMediaUploadListener.bind( this );
this.finishMediaUploadWithSuccess = this.finishMediaUploadWithSuccess.bind( this );
this.finishMediaUploadWithFailure = this.finishMediaUploadWithFailure.bind( this );
this.onImagePressed = this.onImagePressed.bind( this );
}

componentDidMount() {
Expand All @@ -53,6 +59,16 @@ export default class ImageEdit extends React.Component {
this.removeMediaUploadListener();
}

onImagePressed() {
const { attributes } = this.props;

if ( this.state.isUploadInProgress ) {
requestImageUploadCancelDialog( attributes.id );
} else if ( attributes.id && ! isURL( attributes.url ) ) {
requestImageFailedRetryDialog( attributes.id );
}
}

mediaUpload( payload ) {
const { attributes } = this.props;

Expand All @@ -61,15 +77,18 @@ export default class ImageEdit extends React.Component {
}

switch ( payload.state ) {
case MEDIA_ULOAD_STATE_UPLOADING:
this.setState( { progress: payload.progress, isUploadInProgress: true } );
case MEDIA_UPLOAD_STATE_UPLOADING:
this.setState( { progress: payload.progress, isUploadInProgress: true, isUploadFailed: false } );
break;
case MEDIA_ULOAD_STATE_SUCCEEDED:
case MEDIA_UPLOAD_STATE_SUCCEEDED:
this.finishMediaUploadWithSuccess( payload );
break;
case MEDIA_ULOAD_STATE_FAILED:
case MEDIA_UPLOAD_STATE_FAILED:
this.finishMediaUploadWithFailure( payload );
break;
case MEDIA_UPLOAD_STATE_RESET:
this.mediaUploadStateReset( payload );
break;
}
}

Expand All @@ -85,10 +104,15 @@ export default class ImageEdit extends React.Component {
finishMediaUploadWithFailure( payload ) {
const { setAttributes } = this.props;

setAttributes( { url: payload.mediaUrl, id: payload.mediaId } );
this.setState( { isUploadInProgress: false } );
setAttributes( { id: payload.mediaId } );
this.setState( { isUploadInProgress: false, isUploadFailed: true } );
}

this.removeMediaUploadListener();
mediaUploadStateReset( payload ) {
const { setAttributes } = this.props;

setAttributes( { id: payload.mediaId, url: null } );
this.setState( { isUploadInProgress: false, isUploadFailed: false } );
}

addMediaUploadListener() {
Expand Down Expand Up @@ -170,55 +194,64 @@ export default class ImageEdit extends React.Component {
const progress = this.state.progress * 100;

return (
<View style={ { flex: 1 } }>
{ showSpinner && <Spinner progress={ progress } /> }
<BlockControls>
{ toolbarEditButton }
</BlockControls>
<InspectorControls>
{ inlineToolbarButtons }
</InspectorControls>
<ImageSize src={ url } >
{ ( sizes ) => {
const {
imageWidthWithinContainer,
imageHeightWithinContainer,
} = sizes;

let finalHeight = imageHeightWithinContainer;
if ( height > 0 && height < imageHeightWithinContainer ) {
finalHeight = height;
}

let finalWidth = imageWidthWithinContainer;
if ( width > 0 && width < imageWidthWithinContainer ) {
finalWidth = width;
}

return (
<View style={ { flex: 1 } } >
<Image
style={ { width: finalWidth, height: finalHeight, opacity } }
resizeMethod="scale"
source={ { uri: url } }
key={ url }
/>
</View>
);
} }
</ImageSize>
{ ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && (
<View style={ { padding: 12, flex: 1 } }>
<TextInput
style={ { textAlign: 'center' } }
underlineColorAndroid="transparent"
value={ caption }
placeholder={ __( 'Write caption…' ) }
onChangeText={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
/>
</View>
) }
</View>
<TouchableWithoutFeedback onPress={ this.onImagePressed } disabled={ ! isSelected }>
<View style={ { flex: 1 } }>
{ showSpinner && <Spinner progress={ progress } /> }
<BlockControls>
{ toolbarEditButton }
</BlockControls>
<InspectorControls>
{ inlineToolbarButtons }
</InspectorControls>
<ImageSize src={ url } >
{ ( sizes ) => {
const {
imageWidthWithinContainer,
imageHeightWithinContainer,
} = sizes;

let finalHeight = imageHeightWithinContainer;
if ( height > 0 && height < imageHeightWithinContainer ) {
finalHeight = height;
}

let finalWidth = imageWidthWithinContainer;
if ( width > 0 && width < imageWidthWithinContainer ) {
finalWidth = width;
}

return (
<View style={ { flex: 1 } } >
<ImageBackground
style={ { width: finalWidth, height: finalHeight, opacity } }
resizeMethod="scale"
source={ { uri: url } }
key={ url }
>
{ this.state.isUploadFailed &&
<View style={ styles.imageContainer } >
<Dashicon icon={ 'image-rotate' } ariaPressed={ 'dashicon-active' } />
<Text style={ styles.uploadFailedText }>{ __( 'Failed to insert media.\nPlease tap for options.' ) }</Text>
</View>
}
</ImageBackground>
</View>
);
} }
</ImageSize>
{ ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && (
<View style={ { padding: 12, flex: 1 } }>
<TextInput
style={ { textAlign: 'center' } }
underlineColorAndroid="transparent"
value={ caption }
placeholder={ __( 'Write caption…' ) }
onChangeText={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
/>
</View>
) }
</View>
</TouchableWithoutFeedback>
);
}
}
17 changes: 17 additions & 0 deletions packages/block-library/src/image/styles.native.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.imageContainer {
flex: 1;
justify-content: center;
align-items: center;
}

.uploadFailedText {
color: #fff;
font-size: 14;
margin-top: 5;
}

.uploadFailedContainer {
position: absolute;
flex-direction: column;
align-items: center;
}

0 comments on commit 073ea83

Please sign in to comment.