Properly handle max file size (#2248)
* Properly handle max file size * Feedback review
This commit is contained in:
parent
5d9b8a7e06
commit
b5b948e58f
6 changed files with 71 additions and 9 deletions
|
|
@ -10,6 +10,8 @@ import {
|
|||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
import RNFetchBlob from 'rn-fetch-blob';
|
||||
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import {DocumentPicker} from 'react-native-document-picker';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
|
|
@ -27,8 +29,10 @@ export default class AttachmentButton extends PureComponent {
|
|||
children: PropTypes.node,
|
||||
fileCount: PropTypes.number,
|
||||
maxFileCount: PropTypes.number.isRequired,
|
||||
maxFileSize: PropTypes.number.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onShowFileMaxWarning: PropTypes.func,
|
||||
onShowFileSizeWarning: PropTypes.func,
|
||||
theme: PropTypes.object.isRequired,
|
||||
uploadFiles: PropTypes.func.isRequired,
|
||||
wrapper: PropTypes.bool,
|
||||
|
|
@ -293,8 +297,19 @@ export default class AttachmentButton extends PureComponent {
|
|||
return true;
|
||||
};
|
||||
|
||||
uploadFiles = (images) => {
|
||||
this.props.uploadFiles(images);
|
||||
uploadFiles = async (files) => {
|
||||
const file = files[0];
|
||||
if (!file.fileSize | !file.fileName) {
|
||||
const fileInfo = await RNFetchBlob.fs.stat(file.path);
|
||||
file.fileSize = fileInfo.size;
|
||||
file.fileName = fileInfo.filename;
|
||||
}
|
||||
|
||||
if (file.fileSize > this.props.maxFileSize) {
|
||||
this.props.onShowFileSizeWarning(file.fileName);
|
||||
} else {
|
||||
this.props.uploadFiles(files);
|
||||
}
|
||||
};
|
||||
|
||||
handleFileAttachmentOption = (action) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
|
|||
import {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
|
|
@ -20,6 +21,7 @@ export default class FileUploadPreview extends PureComponent {
|
|||
deviceHeight: PropTypes.number.isRequired,
|
||||
files: PropTypes.array.isRequired,
|
||||
filesUploadingForCurrentChannel: PropTypes.bool.isRequired,
|
||||
fileSizeWarning: PropTypes.string,
|
||||
rootId: PropTypes.string,
|
||||
showFileMaxWarning: PropTypes.bool.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
|
|
@ -42,12 +44,17 @@ export default class FileUploadPreview extends PureComponent {
|
|||
render() {
|
||||
const {
|
||||
showFileMaxWarning,
|
||||
fileSizeWarning,
|
||||
channelIsLoading,
|
||||
filesUploadingForCurrentChannel,
|
||||
deviceHeight,
|
||||
files,
|
||||
} = this.props;
|
||||
if (channelIsLoading || (!files.length && !filesUploadingForCurrentChannel)) {
|
||||
|
||||
if (
|
||||
!fileSizeWarning && !showFileMaxWarning &&
|
||||
(channelIsLoading || (!files.length && !filesUploadingForCurrentChannel))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +75,11 @@ export default class FileUploadPreview extends PureComponent {
|
|||
defaultMessage='Uploads limited to 5 files maximum.'
|
||||
/>
|
||||
)}
|
||||
|
||||
{Boolean(fileSizeWarning) &&
|
||||
<Text style={style.warning}>
|
||||
{fileSizeWarning}
|
||||
</Text>
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {handleCommentDraftChanged, handleCommentDraftSelectionChanged} from 'app
|
|||
import {userTyping} from 'app/actions/views/typing';
|
||||
import {getCurrentChannelDraft, getThreadDraft} from 'app/selectors/views';
|
||||
import {getChannelMembersForDm} from 'app/selectors/channel';
|
||||
import {getAllowedServerMaxFileSize} from 'app/utils/file';
|
||||
|
||||
import PostTextbox from './post_textbox';
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ function mapStateToProps(state, ownProps) {
|
|||
userIsOutOfOffice,
|
||||
deactivatedChannel,
|
||||
files: currentDraft.files,
|
||||
maxFileSize: getAllowedServerMaxFileSize(config),
|
||||
maxMessageLength: (config && parseInt(config.MaxPostSize || 0, 10)) || MAX_MESSAGE_LENGTH,
|
||||
theme: getTheme(state),
|
||||
uploadFileRequestStatus: state.requests.files.uploadFiles.status,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {intlShape} from 'react-intl';
|
|||
import Button from 'react-native-button';
|
||||
import {General, RequestStatus} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
import {getFormattedFileSize} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import AttachmentButton from 'app/components/attachment_button';
|
||||
import Autocomplete from 'app/components/autocomplete';
|
||||
|
|
@ -51,6 +52,7 @@ export default class PostTextbox extends PureComponent {
|
|||
currentUserId: PropTypes.string.isRequired,
|
||||
deactivatedChannel: PropTypes.bool.isRequired,
|
||||
files: PropTypes.array,
|
||||
maxFileSize: PropTypes.number.isRequired,
|
||||
maxMessageLength: PropTypes.number.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
rootId: PropTypes.string,
|
||||
|
|
@ -79,6 +81,7 @@ export default class PostTextbox extends PureComponent {
|
|||
contentHeight: INITIAL_HEIGHT,
|
||||
cursorPosition: 0,
|
||||
keyboardType: 'default',
|
||||
fileSizeWarning: null,
|
||||
top: 0,
|
||||
value: props.value,
|
||||
showFileMaxWarning: false,
|
||||
|
|
@ -458,6 +461,23 @@ export default class PostTextbox extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
onShowFileSizeWarning = (filename) => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const fileSizeWarning = formatMessage({
|
||||
id: 'file_upload.fileAbove',
|
||||
defaultMessage: 'File above {max}MB cannot be uploaded: {filename}',
|
||||
}, {
|
||||
max: getFormattedFileSize({size: this.props.maxFileSize}),
|
||||
filename,
|
||||
});
|
||||
|
||||
this.setState({fileSizeWarning}, () => {
|
||||
setTimeout(() => {
|
||||
this.setState({fileSizeWarning: null});
|
||||
}, 3000);
|
||||
});
|
||||
};
|
||||
|
||||
onCloseChannelPress = () => {
|
||||
const {onCloseChannel, channelTeamId} = this.props;
|
||||
this.props.actions.selectPenultimateChannel(channelTeamId);
|
||||
|
|
@ -502,6 +522,7 @@ export default class PostTextbox extends PureComponent {
|
|||
channelIsReadOnly,
|
||||
deactivatedChannel,
|
||||
files,
|
||||
maxFileSize,
|
||||
navigator,
|
||||
rootId,
|
||||
theme,
|
||||
|
|
@ -523,6 +544,7 @@ export default class PostTextbox extends PureComponent {
|
|||
const {
|
||||
contentHeight,
|
||||
cursorPosition,
|
||||
fileSizeWarning,
|
||||
showFileMaxWarning,
|
||||
top,
|
||||
value,
|
||||
|
|
@ -549,8 +571,10 @@ export default class PostTextbox extends PureComponent {
|
|||
theme={theme}
|
||||
navigator={navigator}
|
||||
fileCount={files.length}
|
||||
maxFileSize={maxFileSize}
|
||||
maxFileCount={MAX_FILE_COUNT}
|
||||
onShowFileMaxWarning={this.onShowFileMaxWarning}
|
||||
onShowFileSizeWarning={this.onShowFileSizeWarning}
|
||||
uploadFiles={this.handleUploadFiles}
|
||||
/>
|
||||
);
|
||||
|
|
@ -564,6 +588,7 @@ export default class PostTextbox extends PureComponent {
|
|||
<FileUploadPreview
|
||||
channelId={channelId}
|
||||
files={files}
|
||||
fileSizeWarning={fileSizeWarning}
|
||||
rootId={rootId}
|
||||
showFileMaxWarning={showFileMaxWarning}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
"edit_post.save": "Save",
|
||||
"error.team_not_found.title": "Team Not Found",
|
||||
"file_attachment.download": "Download",
|
||||
"file_upload.fileAbove": "File above {max}MB cannot be uploaded: {filename}",
|
||||
"get_post_link_modal.title": "Copy Permalink",
|
||||
"integrations.add": "Add",
|
||||
"intro_messages.anyMember": " Any member can join and read this channel.",
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ import RNFetchBlob from 'rn-fetch-blob';
|
|||
import {Preferences} from 'mattermost-redux/constants';
|
||||
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import Loading from 'app/components/loading';
|
||||
import PaperPlane from 'app/components/paper_plane';
|
||||
import {MAX_FILE_COUNT} from 'app/constants/post_textbox';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import {getExtensionFromMime} from 'app/utils/file';
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
|
|
@ -263,7 +265,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
};
|
||||
|
||||
loadData = async (items) => {
|
||||
const {token, url} = this.props;
|
||||
const {maxFileSize, token, url} = this.props;
|
||||
if (token && url) {
|
||||
const text = [];
|
||||
const files = [];
|
||||
|
|
@ -312,13 +314,13 @@ export default class ExtensionPost extends PureComponent {
|
|||
|
||||
const value = text.join('\n');
|
||||
|
||||
if (!error) {
|
||||
if (!error && files.length <= MAX_FILE_COUNT && totalSize <= maxFileSize) {
|
||||
this.props.navigation.setParams({
|
||||
post: this.onPost,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({error, files, value, hasPermission: true, totalSize});
|
||||
this.setState({error, files, value, hasPermission: true, totalSize, loaded: true});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -489,7 +491,13 @@ export default class ExtensionPost extends PureComponent {
|
|||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {maxFileSize, token, url} = this.props;
|
||||
const {error, hasPermission, files, totalSize} = this.state;
|
||||
const {error, hasPermission, files, totalSize, loaded} = this.state;
|
||||
|
||||
if (!loaded) {
|
||||
return (
|
||||
<Loading/>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return this.renderErrorMessage(error);
|
||||
|
|
@ -503,7 +511,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
});
|
||||
|
||||
return this.renderErrorMessage(storage);
|
||||
} else if (files.length > 5) {
|
||||
} else if (files.length > MAX_FILE_COUNT) {
|
||||
const fileCount = formatMessage({
|
||||
id: 'mobile.extension.file_limit',
|
||||
defaultMessage: 'Sharing is limited to a maximum of 5 files.',
|
||||
|
|
|
|||
Loading…
Reference in a new issue