diff --git a/app/javascript/mastodon/features/compose/components/upload_progress.tsx b/app/javascript/mastodon/features/compose/components/upload_progress.tsx index 35af03306f..be15917784 100644 --- a/app/javascript/mastodon/features/compose/components/upload_progress.tsx +++ b/app/javascript/mastodon/features/compose/components/upload_progress.tsx @@ -9,48 +9,39 @@ import { reduceMotion } from 'mastodon/initial_state'; interface UploadProgressProps { active: boolean; progress: number; - isProcessing: boolean; + isProcessing?: boolean; } export const UploadProgress: React.FC = ({ active, progress, - isProcessing, + isProcessing = false, }) => { const styles = useSpring({ from: { width: '0%' }, to: { width: `${progress}%` }, - reset: true, - immediate: reduceMotion, + immediate: reduceMotion || !active, // If this is not active, update the UI immediately. }); if (!active) { return null; } - let message; - - if (isProcessing) { - message = ( - - ); - } else { - message = ( - - ); - } - return (
- {message} + {isProcessing ? ( + + ) : ( + + )}
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index d16c8a0d2e..73468c04fe 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -113,6 +113,7 @@ function clearAll(state) { map.set('sensitive', state.get('default_sensitive')); map.set('language', state.get('default_language')); map.update('media_attachments', list => list.clear()); + map.set('progress', 0); map.set('poll', null); map.set('idempotencyKey', uuid()); }); @@ -128,6 +129,7 @@ function appendMedia(state, media, file) { map.update('media_attachments', list => list.push(media.set('unattached', true))); map.set('is_uploading', false); map.set('is_processing', false); + map.set('progress', 0); map.set('resetFileKey', Math.floor((Math.random() * 0x10000))); map.set('idempotencyKey', uuid()); map.update('pending_media_attachments', n => n - 1); @@ -296,6 +298,8 @@ const updatePoll = (state, index, value, maxOptions) => state.updateIn(['poll', return tmp; }); +const calculateProgress = (loaded, total) => Math.min(Math.round((loaded / total) * 100), 100); + /** @type {import('@reduxjs/toolkit').Reducer} */ export const composeReducer = (state = initialState, action) => { if (changeUploadCompose.fulfilled.match(action)) { @@ -402,15 +406,19 @@ export const composeReducer = (state = initialState, action) => { case COMPOSE_UPLOAD_SUCCESS: return appendMedia(state, fromJS(action.media), action.file); case COMPOSE_UPLOAD_FAIL: - return state.set('is_uploading', false).set('is_processing', false).update('pending_media_attachments', n => n - 1); + return state + .set('is_uploading', false) + .set('is_processing', false) + .set('progress', 0) + .update('pending_media_attachments', n => n - 1); case COMPOSE_UPLOAD_UNDO: return removeMedia(state, action.media_id); case COMPOSE_UPLOAD_PROGRESS: - return state.set('progress', Math.round((action.loaded / action.total) * 100)); + return state.set('progress', calculateProgress(action.loaded, action.total)); case THUMBNAIL_UPLOAD_REQUEST: return state.set('isUploadingThumbnail', true); case THUMBNAIL_UPLOAD_PROGRESS: - return state.set('thumbnailProgress', Math.round((action.loaded / action.total) * 100)); + return state.set('thumbnailProgress', calculateProgress(action.loaded, action.total)); case THUMBNAIL_UPLOAD_FAIL: return state.set('isUploadingThumbnail', false); case THUMBNAIL_UPLOAD_SUCCESS: