forked from treehouse/mastodon
Fix upload progress not communicating processing phase in web UI (#19530)
parent
a449ee8654
commit
30ef110224
|
@ -25,10 +25,12 @@ export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
|
||||||
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
||||||
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
||||||
export const COMPOSE_RESET = 'COMPOSE_RESET';
|
export const COMPOSE_RESET = 'COMPOSE_RESET';
|
||||||
|
|
||||||
export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
|
export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
|
||||||
export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
|
export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
|
||||||
export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
|
export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
|
||||||
export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
|
export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
|
||||||
|
export const COMPOSE_UPLOAD_PROCESSING = 'COMPOSE_UPLOAD_PROCESSING';
|
||||||
export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
|
export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
|
||||||
|
|
||||||
export const THUMBNAIL_UPLOAD_REQUEST = 'THUMBNAIL_UPLOAD_REQUEST';
|
export const THUMBNAIL_UPLOAD_REQUEST = 'THUMBNAIL_UPLOAD_REQUEST';
|
||||||
|
@ -268,13 +270,16 @@ export function uploadCompose(files) {
|
||||||
if (status === 200) {
|
if (status === 200) {
|
||||||
dispatch(uploadComposeSuccess(data, f));
|
dispatch(uploadComposeSuccess(data, f));
|
||||||
} else if (status === 202) {
|
} else if (status === 202) {
|
||||||
|
dispatch(uploadComposeProcessing());
|
||||||
|
|
||||||
let tryCount = 1;
|
let tryCount = 1;
|
||||||
|
|
||||||
const poll = () => {
|
const poll = () => {
|
||||||
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
|
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
dispatch(uploadComposeSuccess(response.data, f));
|
dispatch(uploadComposeSuccess(response.data, f));
|
||||||
} else if (response.status === 206) {
|
} else if (response.status === 206) {
|
||||||
let retryAfter = (Math.log2(tryCount) || 1) * 1000;
|
const retryAfter = (Math.log2(tryCount) || 1) * 1000;
|
||||||
tryCount += 1;
|
tryCount += 1;
|
||||||
setTimeout(() => poll(), retryAfter);
|
setTimeout(() => poll(), retryAfter);
|
||||||
}
|
}
|
||||||
|
@ -289,6 +294,10 @@ export function uploadCompose(files) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const uploadComposeProcessing = () => ({
|
||||||
|
type: COMPOSE_UPLOAD_PROCESSING,
|
||||||
|
});
|
||||||
|
|
||||||
export const uploadThumbnail = (id, file) => (dispatch, getState) => {
|
export const uploadThumbnail = (id, file) => (dispatch, getState) => {
|
||||||
dispatch(uploadThumbnailRequest());
|
dispatch(uploadThumbnailRequest());
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import UploadProgressContainer from '../containers/upload_progress_container';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import UploadContainer from '../containers/upload_container';
|
import UploadContainer from '../containers/upload_container';
|
||||||
import SensitiveButtonContainer from '../containers/sensitive_button_container';
|
import SensitiveButtonContainer from '../containers/sensitive_button_container';
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
export default class UploadForm extends ImmutablePureComponent {
|
export default class UploadForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -17,7 +16,7 @@ export default class UploadForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='compose-form__upload-wrapper'>
|
<div className='compose-form__upload-wrapper'>
|
||||||
<UploadProgressContainer icon='upload' message={<FormattedMessage id='upload_progress.label' defaultMessage='Uploading…' />} />
|
<UploadProgressContainer />
|
||||||
|
|
||||||
<div className='compose-form__uploads-wrapper'>
|
<div className='compose-form__uploads-wrapper'>
|
||||||
{mediaIds.map(id => (
|
{mediaIds.map(id => (
|
||||||
|
|
|
@ -3,27 +3,35 @@ import PropTypes from 'prop-types';
|
||||||
import Motion from '../../ui/util/optional_motion';
|
import Motion from '../../ui/util/optional_motion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
export default class UploadProgress extends React.PureComponent {
|
export default class UploadProgress extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
progress: PropTypes.number,
|
progress: PropTypes.number,
|
||||||
icon: PropTypes.string.isRequired,
|
isProcessing: PropTypes.bool,
|
||||||
message: PropTypes.node.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { active, progress, icon, message } = this.props;
|
const { active, progress, isProcessing } = this.props;
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let message;
|
||||||
|
|
||||||
|
if (isProcessing) {
|
||||||
|
message = <FormattedMessage id='upload_progress.processing' defaultMessage='Processing…' />;
|
||||||
|
} else {
|
||||||
|
message = <FormattedMessage id='upload_progress.label' defaultMessage='Uploading…' />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='upload-progress'>
|
<div className='upload-progress'>
|
||||||
<div className='upload-progress__icon'>
|
<div className='upload-progress__icon'>
|
||||||
<Icon id={icon} />
|
<Icon id='upload' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='upload-progress__message'>
|
<div className='upload-progress__message'>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import UploadProgress from '../components/upload_progress';
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
active: state.getIn(['compose', 'is_uploading']),
|
active: state.getIn(['compose', 'is_uploading']),
|
||||||
progress: state.getIn(['compose', 'progress']),
|
progress: state.getIn(['compose', 'progress']),
|
||||||
|
isProcessing: state.getIn(['compose', 'is_processing']),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(UploadProgress);
|
export default connect(mapStateToProps)(UploadProgress);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
COMPOSE_UPLOAD_FAIL,
|
COMPOSE_UPLOAD_FAIL,
|
||||||
COMPOSE_UPLOAD_UNDO,
|
COMPOSE_UPLOAD_UNDO,
|
||||||
COMPOSE_UPLOAD_PROGRESS,
|
COMPOSE_UPLOAD_PROGRESS,
|
||||||
|
COMPOSE_UPLOAD_PROCESSING,
|
||||||
THUMBNAIL_UPLOAD_REQUEST,
|
THUMBNAIL_UPLOAD_REQUEST,
|
||||||
THUMBNAIL_UPLOAD_SUCCESS,
|
THUMBNAIL_UPLOAD_SUCCESS,
|
||||||
THUMBNAIL_UPLOAD_FAIL,
|
THUMBNAIL_UPLOAD_FAIL,
|
||||||
|
@ -136,6 +137,7 @@ function appendMedia(state, media, file) {
|
||||||
}
|
}
|
||||||
map.update('media_attachments', list => list.push(media));
|
map.update('media_attachments', list => list.push(media));
|
||||||
map.set('is_uploading', false);
|
map.set('is_uploading', false);
|
||||||
|
map.set('is_processing', false);
|
||||||
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
map.update('pending_media_attachments', n => n - 1);
|
map.update('pending_media_attachments', n => n - 1);
|
||||||
|
@ -354,10 +356,12 @@ export default function compose(state = initialState, action) {
|
||||||
return state.set('is_changing_upload', false);
|
return state.set('is_changing_upload', false);
|
||||||
case COMPOSE_UPLOAD_REQUEST:
|
case COMPOSE_UPLOAD_REQUEST:
|
||||||
return state.set('is_uploading', true).update('pending_media_attachments', n => n + 1);
|
return state.set('is_uploading', true).update('pending_media_attachments', n => n + 1);
|
||||||
|
case COMPOSE_UPLOAD_PROCESSING:
|
||||||
|
return state.set('is_processing', true);
|
||||||
case COMPOSE_UPLOAD_SUCCESS:
|
case COMPOSE_UPLOAD_SUCCESS:
|
||||||
return appendMedia(state, fromJS(action.media), action.file);
|
return appendMedia(state, fromJS(action.media), action.file);
|
||||||
case COMPOSE_UPLOAD_FAIL:
|
case COMPOSE_UPLOAD_FAIL:
|
||||||
return state.set('is_uploading', false).update('pending_media_attachments', n => n - 1);
|
return state.set('is_uploading', false).set('is_processing', false).update('pending_media_attachments', n => n - 1);
|
||||||
case COMPOSE_UPLOAD_UNDO:
|
case COMPOSE_UPLOAD_UNDO:
|
||||||
return removeMedia(state, action.media_id);
|
return removeMedia(state, action.media_id);
|
||||||
case COMPOSE_UPLOAD_PROGRESS:
|
case COMPOSE_UPLOAD_PROGRESS:
|
||||||
|
|
Loading…
Reference in New Issue