diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 01485deecbd..4866fe3f601 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -26,6 +26,7 @@ const React = require("react"); const ReactDOM = require("react-dom"); import PropTypes from 'prop-types'; import Promise from 'bluebird'; +import filesize from 'filesize'; const classNames = require("classnames"); import { _t } from '../../languageHandler'; @@ -49,8 +50,6 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore"; const DEBUG = false; let debuglog = function() {}; -let mediaLimitCache = null; - const BROWSER_SUPPORTS_SANDBOX = 'sandbox' in document.createElement('iframe'); if (DEBUG) { @@ -96,9 +95,9 @@ module.exports = React.createClass({ roomLoading: true, peekLoading: false, shouldPeek: true, - - // Media limits for uploading, this may change. - mediaLimits: {}, + + // Media limits for uploading. + mediaConfig: undefined, // The event to be scrolled to initially initialEventId: null, @@ -152,24 +151,31 @@ module.exports = React.createClass({ MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember); MatrixClientPeg.get().on("RoomMember.membership", this.onRoomMemberMembership); MatrixClientPeg.get().on("accountData", this.onAccountData); - this._fetchMediaLimits(); + this._fetchMediaConfig(); // Start listening for RoomViewStore updates this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate); this._onRoomViewStoreUpdate(true); }, - _fetchMediaLimits: function(invalidateCache: boolean = false) { - let limits; - if(invalidateCache || mediaLimitCache == null) { - MatrixClientPeg.get().getMediaLimits().then((_limits) => { - limits = _limits; - }).catch(() => { - // Media repo can't or won't report limits, so provide an empty object (no limits). - limits = {}; - }); - mediaLimitCache = limits; + _fetchMediaConfig: function(invalidateCache: boolean = false) { + /// NOTE: Using global here so we don't make repeated requests for the + /// config every time we swap room. + if(global.mediaConfig !== undefined && !invalidateCache) { + this.setState({mediaConfig: global.mediaConfig}); + return; } - this.state.mediaLimits = limits; + console.log("[Media Config] Fetching"); + MatrixClientPeg.get().getMediaConfig().then((config) => { + console.log("[Media Config] Fetched config:", config); + return config; + }).catch(() => { + // Media repo can't or won't report limits, so provide an empty object (no limits). + console.log("[Media Config] Could not fetch config, so not limiting uploads."); + return {}; + }).then((config) => { + global.mediaConfig = config; + this.setState({mediaConfig: config}); + }); }, _onRoomViewStoreUpdate: function(initial) { @@ -501,8 +507,8 @@ module.exports = React.createClass({ case 'notifier_enabled': case 'upload_failed': // 413: File was too big or upset the server in some way. - if(payload.data.error.http_status === 413) { - this._fetchMediaLimits(true); + if(payload.error.http_status === 413) { + this._fetchMediaConfig(true); } case 'upload_started': case 'upload_finished': @@ -935,6 +941,15 @@ module.exports = React.createClass({ this.setState({ draggingFile: false }); }, + isFileUploadAllowed(file) { + if (this.state.mediaConfig !== undefined && + this.state.mediaConfig["m.upload.size"] !== undefined && + file.size > this.state.mediaConfig["m.upload.size"]) { + return _t("File is too big. Maximum file size is %(fileSize)s", {fileSize: filesize(this.state.mediaConfig["m.upload.size"])}); + } + return true; + }, + uploadFile: async function(file) { dis.dispatch({action: 'focus_composer'}); @@ -1677,7 +1692,7 @@ module.exports = React.createClass({ callState={this.state.callState} disabled={this.props.disabled} showApps={this.state.showApps} - mediaLimits={this.state.mediaLimits} + uploadAllowed={this.isFileUploadAllowed} />; } diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 1a80a0be4fe..f0c73a67af8 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -16,7 +16,6 @@ limitations under the License. */ import React from 'react'; import PropTypes from 'prop-types'; -import filesize from 'filesize'; import { _t } from '../../../languageHandler'; import CallHandler from '../../../CallHandler'; import MatrixClientPeg from '../../../MatrixClientPeg'; @@ -102,15 +101,6 @@ export default class MessageComposer extends React.Component { this.uploadFiles(tfiles); } - isFileUploadAllowed(file) { - if (this.props.mediaLimits !== undefined && - this.props.mediaLimits.upload_size !== undefined && - file.size > this.props.mediaLimits.upload_size) { - return _t("File is too big. Maximum file size is %(fileSize)s", {fileSize: filesize(this.mediaLimits.upload_size)}); - } - return true; - } - uploadFiles(files) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const TintableSvg = sdk.getComponent("elements.TintableSvg"); @@ -120,7 +110,7 @@ export default class MessageComposer extends React.Component { const failedFiles = []; for (let i=0; i { files[i].name || _t('Attachment') } @@ -128,7 +118,7 @@ export default class MessageComposer extends React.Component { fileList.push(files[i]); } else { failedFiles.push(
  • - { files[i].name || _t('Attachment') } { _t('Reason') + ": " + fileAcceptedOrError} + { files[i].name || _t('Attachment') }

    { _t('Reason') + ": " + fileAcceptedOrError}

  • ); } } @@ -158,6 +148,12 @@ export default class MessageComposer extends React.Component { ); + let buttonText; + if (acceptedFiles.length > 0 && failedFiles.length > 0) { + buttonText = "Upload selected" + } else if (failedFiles.length > 0) { + buttonText = "Close" + } Modal.createTrackedDialog('Upload Files confirmation', '', QuestionDialog, { title: _t('Upload Files'), @@ -168,6 +164,8 @@ export default class MessageComposer extends React.Component { { replyToWarning } ), + hasCancelButton: acceptedFiles.length > 0, + button: buttonText, onFinished: (shouldUpload) => { if (shouldUpload) { // MessageComposer shouldn't have to rely on its parent passing in a callback to upload a file @@ -425,7 +423,8 @@ MessageComposer.propTypes = { // callback when a file to upload is chosen uploadFile: PropTypes.func.isRequired, - mediaLimits: PropTypes.object, + // function to test whether a file should be allowed to be uploaded. + uploadAllowed: PropTypes.func.isRequired, // string representing the current room app drawer state showApps: PropTypes.bool