diff --git a/app/utils/file.js b/app/utils/file.js
index 74550510a..074e16912 100644
--- a/app/utils/file.js
+++ b/app/utils/file.js
@@ -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;
+};
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index c3a439fd7..50bfca07d 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -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",
diff --git a/share_extension/android/extension_post/extension_post.js b/share_extension/android/extension_post/extension_post.js
index 383e97f90..749e950a8 100644
--- a/share_extension/android/extension_post/extension_post.js
+++ b/share_extension/android/extension_post/extension_post.js
@@ -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 (
+
+
+
+ {message}
+
+
+
+ );
+ };
+
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}`}
);
@@ -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 (
-
-
-
- {formatMessage({
- id: 'mobile.extension.permission',
- defaultMessage: 'Mattermost needs access to the device storage to share files.'
- })}
-
-
-
- );
- } else if (files.length > 5) {
- return (
-
-
-
- {formatMessage({
- id: 'mobile.extension.file_limit',
- defaultMessage: 'Sharing is limited to a maximum of 5 files.'
- })}
-
-
-
- );
- } else if (token && url) {
return (
@@ -493,16 +507,12 @@ export default class ExtensionPost extends PureComponent {
);
}
- return (
-
-
- {formatMessage({
- id: 'mobile.extension.authentication_required',
- defaultMessage: 'Authentication required: Please first login using the app.'
- })}
-
-
- );
+ const loginNeeded = formatMessage({
+ id: 'mobile.extension.authentication_required',
+ defaultMessage: 'Authentication required: Please first login using the app.'
+ });
+
+ return this.renderErrorMessage(loginNeeded);
}
}
diff --git a/share_extension/android/extension_post/index.js b/share_extension/android/extension_post/index.js
index 8cf2c4252..6893718ef 100644
--- a/share_extension/android/extension_post/index.js
+++ b/share_extension/android/extension_post/index.js
@@ -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
diff --git a/share_extension/ios/extension_post.js b/share_extension/ios/extension_post.js
index 817c1f6bb..0dfca21fe 100644
--- a/share_extension/ios/extension_post.js
+++ b/share_extension/ios/extension_post.js
@@ -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 (
{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})})}
);