diff options
author | David Lu <david.lu@hotmail.com> | 2016-05-05 19:23:15 -0400 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2016-05-05 19:23:15 -0400 |
commit | e89868630128499dfaa68a9cb132d1814da7ea8d (patch) | |
tree | f3b3ef0c9b79eb222984405986c692e7bba9590b /webapp/components/file_upload.jsx | |
parent | f2e788f4b12517759e016a9f48633597bed82e8f (diff) | |
download | chat-e89868630128499dfaa68a9cb132d1814da7ea8d.tar.gz chat-e89868630128499dfaa68a9cb132d1814da7ea8d.tar.bz2 chat-e89868630128499dfaa68a9cb132d1814da7ea8d.zip |
[PLT-2802] Memory leaks in file upload shortcuts (#2889)
* Added file upload shortcuts (CTRL+U and CMD+U)
* Added KeyCode for U
* Preventing memory leaks
Diffstat (limited to 'webapp/components/file_upload.jsx')
-rw-r--r-- | webapp/components/file_upload.jsx | 181 |
1 files changed, 93 insertions, 88 deletions
diff --git a/webapp/components/file_upload.jsx b/webapp/components/file_upload.jsx index 8e631ac95..1201948d8 100644 --- a/webapp/components/file_upload.jsx +++ b/webapp/components/file_upload.jsx @@ -129,9 +129,7 @@ class FileUpload extends React.Component { } componentDidMount() { - var inputDiv = ReactDOM.findDOMNode(this.refs.input); var self = this; - const {formatMessage} = this.props.intl; if (this.props.postType === 'post') { $('.row.main').dragster({ @@ -177,109 +175,116 @@ class FileUpload extends React.Component { }); } - document.addEventListener('paste', (e) => { - if (!e.clipboardData) { - return; - } + document.addEventListener('paste', this.pasteUpload); + document.addEventListener('keydown', this.keyUpload); + } - var textarea = $(inputDiv.parentNode.parentNode).find('.custom-textarea')[0]; + componentWillUnmount() { + let target; + if (this.props.postType === 'post') { + target = $('.row.main'); + } else { + target = $('.post-right__container'); + } - if (textarea !== e.target && !$.contains(textarea, e.target)) { - return; - } + document.removeEventListener('paste', this.pasteUpload); + document.removeEventListener('keydown', this.keyUpload); - self.props.onUploadError(null); + // jquery-dragster doesn't provide a function to unregister itself so do it manually + target.off('dragenter dragleave dragover drop dragster:enter dragster:leave dragster:over dragster:drop'); + } - // This looks redundant, but must be done this way due to - // setState being an asynchronous call - var items = e.clipboardData.items; - var numItems = 0; - if (items) { - for (let i = 0; i < items.length; i++) { - if (items[i].type.indexOf('image') !== -1) { - var testExt = items[i].type.split('/')[1].toLowerCase(); + pasteUpload(e) { + var inputDiv = ReactDOM.findDOMNode(this.refs.input); + const {formatMessage} = this.props.intl; - if (Constants.IMAGE_TYPES.indexOf(testExt) < 0) { - continue; - } + if (!e.clipboardData) { + return; + } - numItems++; - } - } + var textarea = $(inputDiv.parentNode.parentNode).find('.custom-textarea')[0]; - var numToUpload = Math.min(Constants.MAX_UPLOAD_FILES - self.props.getFileCount(ChannelStore.getCurrentId()), numItems); + if (textarea !== e.target && !$.contains(textarea, e.target)) { + return; + } - if (numItems > numToUpload) { - self.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES})); - } + self.props.onUploadError(null); - for (var i = 0; i < items.length && i < numToUpload; i++) { - if (items[i].type.indexOf('image') !== -1) { - var file = items[i].getAsFile(); - - var ext = items[i].type.split('/')[1].toLowerCase(); - - if (Constants.IMAGE_TYPES.indexOf(ext) < 0) { - continue; - } - - var channelId = self.props.channelId || ChannelStore.getCurrentId(); - - // generate a unique id that can be used by other components to refer back to this file upload - var clientId = Utils.generateId(); - - var d = new Date(); - var hour; - if (d.getHours() < 10) { - hour = '0' + d.getHours(); - } else { - hour = String(d.getHours()); - } - var min; - if (d.getMinutes() < 10) { - min = '0' + d.getMinutes(); - } else { - min = String(d.getMinutes()); - } - - const name = formatMessage(holders.pasted) + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' ' + hour + '-' + min + '.' + ext; - - const request = Client.uploadFile(file, - name, - channelId, - clientId, - self.fileUploadSuccess.bind(self, channelId), - self.fileUploadFail.bind(self, clientId) - ); - - const requests = self.state.requests; - requests[clientId] = request; - self.setState({requests}); - - self.props.onUploadStart([clientId], channelId); + // This looks redundant, but must be done this way due to + // setState being an asynchronous call + var items = e.clipboardData.items; + var numItems = 0; + if (items) { + for (let i = 0; i < items.length; i++) { + if (items[i].type.indexOf('image') !== -1) { + var testExt = items[i].type.split('/')[1].toLowerCase(); + + if (Constants.IMAGE_TYPES.indexOf(testExt) < 0) { + continue; } + + numItems++; } } - }); - document.addEventListener('keydown', (e) => { - //CTRL+U or CMD+U for file uploads - if ((e.ctrlKey || e.metaKey) && e.keyCode === Constants.KeyCodes.U) { - $(this.refs.input).focus().trigger('click'); + var numToUpload = Math.min(Constants.MAX_UPLOAD_FILES - self.props.getFileCount(ChannelStore.getCurrentId()), numItems); + + if (numItems > numToUpload) { + self.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES})); } - }); - } - componentWillUnmount() { - let target; - if (this.props.postType === 'post') { - target = $('.row.main'); - } else { - target = $('.post-right__container'); + for (var i = 0; i < items.length && i < numToUpload; i++) { + if (items[i].type.indexOf('image') !== -1) { + var file = items[i].getAsFile(); + + var ext = items[i].type.split('/')[1].toLowerCase(); + + if (Constants.IMAGE_TYPES.indexOf(ext) < 0) { + continue; + } + var channelId = self.props.channelId || ChannelStore.getCurrentId(); + + // generate a unique id that can be used by other components to refer back to this file upload + var clientId = Utils.generateId(); + + var d = new Date(); + var hour; + if (d.getHours() < 10) { + hour = '0' + d.getHours(); + } else { + hour = String(d.getHours()); + } + var min; + if (d.getMinutes() < 10) { + min = '0' + d.getMinutes(); + } else { + min = String(d.getMinutes()); + } + + const name = formatMessage(holders.pasted) + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' ' + hour + '-' + min + '.' + ext; + + const request = Client.uploadFile(file, + name, + channelId, + clientId, + self.fileUploadSuccess.bind(self, channelId), + self.fileUploadFail.bind(self, clientId) + ); + + const requests = self.state.requests; + requests[clientId] = request; + self.setState({requests}); + + self.props.onUploadStart([clientId], channelId); + } + } } + } - // jquery-dragster doesn't provide a function to unregister itself so do it manually - target.off('dragenter dragleave dragover drop dragster:enter dragster:leave dragster:over dragster:drop'); + keyUpload(e) { + if ((e.ctrlKey || e.metaKey) && e.keyCode === Constants.KeyCodes.U) { + $(this.refs.input).focus().trigger('click'); + } } cancelUpload(clientId) { |