[ICU-676] Make the app extensions follow the max file size that the server accepts (#1411)
* Android Share extension follows server config file size limit * iOS Share extention follows config file size limit * feedback review
This commit is contained in:
parent
439131578a
commit
509fe37f1f
5 changed files with 75 additions and 53 deletions
|
|
@ -6,6 +6,7 @@ import {lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
|||
import {DeviceTypes} from 'app/constants/';
|
||||
|
||||
const {DOCUMENTS_PATH, VIDEOS_PATH} = DeviceTypes;
|
||||
const DEFAULT_SERVER_MAX_FILE_SIZE = 50 * 1024 * 1024;// 50 Mb
|
||||
|
||||
export function generateId() {
|
||||
// Implementation taken from http://stackoverflow.com/a/2117523
|
||||
|
|
@ -79,3 +80,7 @@ export function buildFileUploadData(file) {
|
|||
export const encodeHeaderURIStringToUTF8 = (string) => {
|
||||
return encodeURIComponent(string) + '"; filename*="utf-8\'\'' + encodeURIComponent(string);
|
||||
};
|
||||
|
||||
export const getAllowedServerMaxFileSize = (config) => {
|
||||
return config.MaxFileSize ? parseInt(config.MaxFileSize, 10) : DEFAULT_SERVER_MAX_FILE_SIZE;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2024,7 +2024,7 @@
|
|||
"mobile.error_handler.title": "Unexpected error occurred",
|
||||
"mobile.extension.authentication_required": "Authentication required: Please first login using the app.",
|
||||
"mobile.extension.file_limit": "Sharing is limited to a maximum of 5 files.",
|
||||
"mobile.extension.max_file_size": "File attachments shared in Mattermost must be less than 20 Mb.",
|
||||
"mobile.extension.max_file_size": "File attachments shared in Mattermost must be less than {size}.",
|
||||
"mobile.extension.permission": "Mattermost needs access to the device storage to share files.",
|
||||
"mobile.extension.posting": "Posting...",
|
||||
"mobile.extension.title": "Share in Mattermost",
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ import {
|
|||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
import Video from 'react-native-video';
|
||||
import LocalAuth from 'react-native-local-auth';
|
||||
import RNFetchBlob from 'react-native-fetch-blob';
|
||||
|
||||
import {Preferences} from 'mattermost-redux/constants';
|
||||
import {lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
||||
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import PaperPlane from 'app/components/paper_plane';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
|
|
@ -57,6 +58,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
static propTypes = {
|
||||
channelId: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
maxFileSize: PropTypes.number.isRequired,
|
||||
navigation: PropTypes.object.isRequired,
|
||||
teamId: PropTypes.string.isRequired,
|
||||
token: PropTypes.string,
|
||||
|
|
@ -129,6 +131,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
files: [],
|
||||
hasPermission: null,
|
||||
teamId: props.teamId,
|
||||
totalSize: 0,
|
||||
value: ''
|
||||
};
|
||||
}
|
||||
|
|
@ -261,6 +264,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
if (token && url) {
|
||||
const text = [];
|
||||
const files = [];
|
||||
let totalSize = 0;
|
||||
|
||||
this.props.navigation.setParams({
|
||||
post: this.onPost
|
||||
|
|
@ -276,11 +280,14 @@ export default class ExtensionPost extends PureComponent {
|
|||
const fullPath = item.value;
|
||||
const filename = fullPath.replace(/^.*[\\/]/, '');
|
||||
const extension = filename.split('.').pop();
|
||||
const fileSize = await RNFetchBlob.fs.stat(fullPath);
|
||||
totalSize += fileSize.size;
|
||||
files.push({
|
||||
extension,
|
||||
filename,
|
||||
fullPath,
|
||||
mimeType: lookupMimeType(filename.toLowerCase()),
|
||||
size: getFormattedFileSize(fileSize),
|
||||
type: item.type
|
||||
});
|
||||
break;
|
||||
|
|
@ -290,7 +297,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
|
||||
const value = text.join('\n');
|
||||
|
||||
this.setState({files, value, hasPermission: true});
|
||||
this.setState({files, value, hasPermission: true, totalSize});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -355,6 +362,20 @@ export default class ExtensionPost extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
renderErrorMessage = (message) => {
|
||||
return (
|
||||
<View
|
||||
style={styles.flex}
|
||||
>
|
||||
<View style={styles.unauthenticatedContainer}>
|
||||
<Text style={styles.unauthenticated}>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderFiles = () => {
|
||||
const {files} = this.state;
|
||||
|
||||
|
|
@ -425,7 +446,7 @@ export default class ExtensionPost extends PureComponent {
|
|||
numberOfLines={1}
|
||||
style={styles.filename}
|
||||
>
|
||||
{file.filename}
|
||||
{`${file.size} - ${file.filename}`}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
|
|
@ -446,40 +467,33 @@ export default class ExtensionPost extends PureComponent {
|
|||
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {token, url} = this.props;
|
||||
const {hasPermission, files} = this.state;
|
||||
const {maxFileSize, token, url} = this.props;
|
||||
const {hasPermission, files, totalSize} = this.state;
|
||||
|
||||
if (token && url) {
|
||||
if (hasPermission === false) {
|
||||
const storage = formatMessage({
|
||||
id: 'mobile.extension.permission',
|
||||
defaultMessage: 'Mattermost needs access to the device storage to share files.'
|
||||
});
|
||||
|
||||
return this.renderErrorMessage(storage);
|
||||
} else if (files.length > 5) {
|
||||
const fileCount = formatMessage({
|
||||
id: 'mobile.extension.file_limit',
|
||||
defaultMessage: 'Sharing is limited to a maximum of 5 files.'
|
||||
});
|
||||
|
||||
return this.renderErrorMessage(fileCount);
|
||||
} else if (totalSize > maxFileSize) {
|
||||
const maxSize = formatMessage({
|
||||
id: 'mobile.extension.max_file_size',
|
||||
defaultMessage: 'File attachments shared in Mattermost must be less than {size}.'
|
||||
}, {size: getFormattedFileSize({size: maxFileSize})});
|
||||
|
||||
return this.renderErrorMessage(maxSize);
|
||||
}
|
||||
|
||||
if (hasPermission === false) {
|
||||
return (
|
||||
<View
|
||||
style={styles.flex}
|
||||
>
|
||||
<View style={styles.unauthenticatedContainer}>
|
||||
<Text style={styles.unauthenticated}>
|
||||
{formatMessage({
|
||||
id: 'mobile.extension.permission',
|
||||
defaultMessage: 'Mattermost needs access to the device storage to share files.'
|
||||
})}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
} else if (files.length > 5) {
|
||||
return (
|
||||
<View
|
||||
style={styles.flex}
|
||||
>
|
||||
<View style={styles.unauthenticatedContainer}>
|
||||
<Text style={styles.unauthenticated}>
|
||||
{formatMessage({
|
||||
id: 'mobile.extension.file_limit',
|
||||
defaultMessage: 'Sharing is limited to a maximum of 5 files.'
|
||||
})}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
} else if (token && url) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.wrapper}>
|
||||
|
|
@ -493,16 +507,12 @@ export default class ExtensionPost extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.unauthenticatedContainer}>
|
||||
<Text style={styles.unauthenticated}>
|
||||
{formatMessage({
|
||||
id: 'mobile.extension.authentication_required',
|
||||
defaultMessage: 'Authentication required: Please first login using the app.'
|
||||
})}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
const loginNeeded = formatMessage({
|
||||
id: 'mobile.extension.authentication_required',
|
||||
defaultMessage: 'Authentication required: Please first login using the app.'
|
||||
});
|
||||
|
||||
return this.renderErrorMessage(loginNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,18 @@ import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels'
|
|||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {getAllowedServerMaxFileSize} from 'app/utils/file';
|
||||
|
||||
import ExtensionPost from './extension_post';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const {token, url} = state.entities.general.credentials;
|
||||
const {config, credentials} = state.entities.general;
|
||||
const {token, url} = credentials;
|
||||
|
||||
return {
|
||||
channelId: getCurrentChannelId(state),
|
||||
currentUserId: getCurrentUserId(state),
|
||||
maxFileSize: getAllowedServerMaxFileSize(config),
|
||||
teamId: getCurrentTeamId(state),
|
||||
token,
|
||||
url
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import {Client4} from 'mattermost-redux/client';
|
|||
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
import {generateId} from 'app/utils/file';
|
||||
import {generateId, getAllowedServerMaxFileSize} from 'app/utils/file';
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import Config from 'assets/config';
|
||||
|
|
@ -258,7 +258,10 @@ export default class ExtensionPost extends PureComponent {
|
|||
renderBody = (styles) => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {authenticated, theme} = this.props;
|
||||
const {error, sending, totalSize, value} = this.state;
|
||||
const {entities, error, sending, totalSize, value} = this.state;
|
||||
const {config} = entities.general;
|
||||
const serverMaxFileSize = getAllowedServerMaxFileSize(config);
|
||||
const maxSize = Math.min(MAX_FILE_SIZE, serverMaxFileSize);
|
||||
|
||||
if (sending) {
|
||||
return (
|
||||
|
|
@ -274,14 +277,14 @@ export default class ExtensionPost extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
if (totalSize >= MAX_FILE_SIZE) {
|
||||
if (totalSize >= maxSize) {
|
||||
return (
|
||||
<View style={styles.unauthenticatedContainer}>
|
||||
<Text style={styles.unauthenticated}>
|
||||
{formatMessage({
|
||||
id: 'mobile.extension.max_file_size',
|
||||
defaultMessage: 'File attachments shared in Mattermost must be less than 20 Mb.'
|
||||
})}
|
||||
defaultMessage: 'File attachments shared in Mattermost must be less than {size}.'
|
||||
}, {size: getFormattedFileSize({size: maxSize})})}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue