diff --git a/app/actions/views/file_upload.js b/app/actions/views/file_upload.js index a9c62124a..14753182f 100644 --- a/app/actions/views/file_upload.js +++ b/app/actions/views/file_upload.js @@ -107,6 +107,14 @@ export function handleClearFiles(channelId, rootId) { }; } +export function handleClearFailedFiles(channelId, rootId) { + return { + type: ViewTypes.CLEAR_FAILED_FILES_FOR_POST_DRAFT, + channelId, + rootId + }; +} + export function handleRemoveFile(clientId, channelId, rootId) { return { type: ViewTypes.REMOVE_FILE_FROM_POST_DRAFT, diff --git a/app/components/post_textbox/index.js b/app/components/post_textbox/index.js index de3571ba6..a24489d00 100644 --- a/app/components/post_textbox/index.js +++ b/app/components/post_textbox/index.js @@ -13,7 +13,7 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {executeCommand} from 'app/actions/views/command'; import {addReactionToLatestPost} from 'app/actions/views/emoji'; import {handlePostDraftChanged, handlePostDraftSelectionChanged} from 'app/actions/views/channel'; -import {handleClearFiles, handleRemoveLastFile, handleUploadFiles} from 'app/actions/views/file_upload'; +import {handleClearFiles, handleClearFailedFiles, handleRemoveLastFile, handleUploadFiles} from 'app/actions/views/file_upload'; import {handleCommentDraftChanged, handleCommentDraftSelectionChanged} from 'app/actions/views/thread'; import {getTheme} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentChannelDraft, getThreadDraft} from 'app/selectors/views'; @@ -42,6 +42,7 @@ function mapDispatchToProps(dispatch) { createPost, executeCommand, handleClearFiles, + handleClearFailedFiles, handleCommentDraftChanged, handlePostDraftChanged, handleRemoveLastFile, diff --git a/app/components/post_textbox/post_textbox.js b/app/components/post_textbox/post_textbox.js index 638923395..1af1b4975 100644 --- a/app/components/post_textbox/post_textbox.js +++ b/app/components/post_textbox/post_textbox.js @@ -29,6 +29,7 @@ class PostTextbox extends PureComponent { handleCommentDraftChanged: PropTypes.func.isRequired, handlePostDraftChanged: PropTypes.func.isRequired, handleClearFiles: PropTypes.func.isRequired, + handleClearFailedFiles: PropTypes.func.isRequired, handleRemoveLastFile: PropTypes.func.isRequired, handleUploadFiles: PropTypes.func.isRequired, userTyping: PropTypes.func.isRequired, @@ -208,7 +209,7 @@ class PostTextbox extends PureComponent { return; } - const {files} = this.props; + const {actions, channelId, files, rootId} = this.props; const {value} = this.state; const isReactionMatch = value.match(IS_REACTION_REGEX); @@ -235,7 +236,11 @@ class PostTextbox extends PureComponent { text: intl.formatMessage({id: 'mobile.channel_info.alertNo', defaultMessage: 'No'}) }, { text: intl.formatMessage({id: 'mobile.channel_info.alertYes', defaultMessage: 'Yes'}), - onPress: this.sendMessage + onPress: () => { + // Remove only failed files + actions.handleClearFailedFiles(channelId, rootId); + this.sendMessage(); + } }], ); } else { diff --git a/app/constants/view.js b/app/constants/view.js index 2ccaa3813..7914a8d62 100644 --- a/app/constants/view.js +++ b/app/constants/view.js @@ -33,6 +33,7 @@ const ViewTypes = keyMirror({ RETRY_UPLOAD_FILE_FOR_POST: null, CLEAR_FILES_FOR_POST_DRAFT: null, + CLEAR_FAILED_FILES_FOR_POST_DRAFT: null, REMOVE_FILE_FROM_POST_DRAFT: null, REMOVE_LAST_FILE_FROM_POST_DRAFT: null, diff --git a/app/reducers/views/channel.js b/app/reducers/views/channel.js index 9c2b908c2..8c239599e 100644 --- a/app/reducers/views/channel.js +++ b/app/reducers/views/channel.js @@ -188,6 +188,18 @@ function handleRemoveLastFileFromPostDraft(state, action) { }; } +function handleRemoveFailedFilesFromPostDraft(state, action) { + if (action.rootId) { + return state; + } + + const files = state[action.channelId].files.filter((f) => !f.failed); + return { + ...state, + [action.channelId]: Object.assign({}, state[action.channelId], {files}) + }; +} + function drafts(state = {}, action) { // eslint-disable-line complexity switch (action.type) { case ViewTypes.POST_DRAFT_CHANGED: @@ -208,6 +220,8 @@ function drafts(state = {}, action) { // eslint-disable-line complexity return handleUploadFilesFailure(state, action); case ViewTypes.CLEAR_FILES_FOR_POST_DRAFT: return handleClearFilesForPostDraft(state, action); + case ViewTypes.CLEAR_FAILED_FILES_FOR_POST_DRAFT: + return handleRemoveFailedFilesFromPostDraft(state, action); case ViewTypes.REMOVE_FILE_FROM_POST_DRAFT: return handleRemoveFileFromPostDraft(state, action); case ViewTypes.REMOVE_LAST_FILE_FROM_POST_DRAFT: diff --git a/app/reducers/views/thread.js b/app/reducers/views/thread.js index 489e2d9f8..bb372422b 100644 --- a/app/reducers/views/thread.js +++ b/app/reducers/views/thread.js @@ -192,6 +192,18 @@ function handleRemoveLastFromPostDraft(state, action) { }; } +function handleRemoveFailedFilesFromPostDraft(state, action) { + if (!action.rootId) { + return state; + } + + const files = state[action.rootId].files.filter((f) => !f.failed); + return { + ...state, + [action.rootId]: Object.assign({}, state[action.rootId], {files}) + }; +} + function drafts(state = {}, action) { // eslint-disable-line complexity switch (action.type) { case ViewTypes.COMMENT_DRAFT_CHANGED: @@ -212,6 +224,8 @@ function drafts(state = {}, action) { // eslint-disable-line complexity return handleUploadFilesFailure(state, action); case ViewTypes.CLEAR_FILES_FOR_POST_DRAFT: return handleClearFilesForPostDraft(state, action); + case ViewTypes.CLEAR_FAILED_FILES_FOR_POST_DRAFT: + return handleRemoveFailedFilesFromPostDraft(state, action); case ViewTypes.REMOVE_FILE_FROM_POST_DRAFT: return handleRemoveFileFromPostDraft(state, action); case ViewTypes.REMOVE_LAST_FILE_FROM_POST_DRAFT: