From 25d51ef4eb142f2347ce18a74225a1311645600b Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Mon, 15 Jul 2019 16:06:59 +0200 Subject: [PATCH] Refactor FileUpload, abstract out some logic --- src/components/chat.js | 11 +++--- src/components/fileUpload.js | 67 ++++++++++++++++++------------------ src/lib/file-to-data-url.js | 19 ++++++++++ src/lib/riot-utils.js | 23 ++++--------- src/lib/with-element.js | 15 ++++++++ 5 files changed, 77 insertions(+), 58 deletions(-) create mode 100644 src/lib/file-to-data-url.js create mode 100644 src/lib/with-element.js diff --git a/src/components/chat.js b/src/components/chat.js index f4a471f..a3b5df8 100644 --- a/src/components/chat.js +++ b/src/components/chat.js @@ -16,6 +16,7 @@ const generateJdenticon = require("../lib/generate-jdenticon"); const generateThumbnailUrl = require("../lib/generate-thumbnail-url"); const groupEvents = require("../lib/group-events"); const parseMXC = require("../lib/parse-mxc"); +const withElement = require("../lib/with-element"); let eventFunctions = { plaintext: function() { @@ -163,13 +164,9 @@ let chat = create({ }); function EventGroup({ events, room, client, onReplyClick }) { - let [ avatarRef, setAvatarRef ] = React.useState(); - - React.useEffect(() => { - if (avatarRef != null) { - generateJdenticon(user.userId).update(avatarRef); - } - }, [ avatarRef ]); + let setAvatarRef = withElement((element) => { + generateJdenticon(user.userId).update(element); + }); let user = client.getUser(events[0].sender); diff --git a/src/components/fileUpload.js b/src/components/fileUpload.js index 29a62e1..da52d07 100644 --- a/src/components/fileUpload.js +++ b/src/components/fileUpload.js @@ -1,45 +1,44 @@ 'use strict'; -const React = require('react'); -const create = require('create-react-class'); -let fileUpload = create({ - displayName: "FileUpload", +const Promise = require("bluebird"); +const React = require('react'); - setFileRef: function(e) { - if (e != null) { - e.addEventListener('change', this.startUpload); - this.setState({ - fileRef: e - }); - } - }, +const withElement = require("../lib/with-element"); +const fileToDataUrl = require("../lib/file-to-data-url"); - startUpload: function(e) { - Array.from(e.target.files).forEach((file) => { +module.exports = function FileUpload({ addUpload }) { + function handleChange(event) { + return Promise.map(Array.from(event.target.files), (file) => { if (file.type.startsWith("image/")) { - let reader = new FileReader(); - reader.onloadend = () => { - let fileObject = { + return Promise.try(() => { + return fileToDataUrl(file); + }).then((url) => { + return addUpload({ file: file, - preview: reader.result - }; - this.props.addUpload(fileObject); - }; - reader.readAsDataURL(file); + preview: url + }); + }); } else { - this.props.addUpload({file: file, preview: "/icons/file.svg"}); + return addUpload({ + file: file, + preview: "/icons/file.svg" + }); } }); - }, - - render: function() { - return ( -
- - -
- ); } -}); -module.exports = fileUpload; + let setFileRef = withElement((element) => { + element.addEventListener("change", handleChange); + + return function() { + element.removeEventListener("change", handleChange); + }; + }); + + return ( +
+ + +
+ ); +}; diff --git a/src/lib/file-to-data-url.js b/src/lib/file-to-data-url.js new file mode 100644 index 0000000..0bd6e74 --- /dev/null +++ b/src/lib/file-to-data-url.js @@ -0,0 +1,19 @@ +"use strict"; + +const Promise = require("bluebird"); + +module.exports = function readFileAsDataUrl(dataUrl) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = function(event) { + resolve(event.target.result); + }; + + reader.onerror = function(error) { + reject(error); + }; + + reader.readAsDataURL(dataUrl); + }); +}; diff --git a/src/lib/riot-utils.js b/src/lib/riot-utils.js index 7bb4b19..d9aa99f 100644 --- a/src/lib/riot-utils.js +++ b/src/lib/riot-utils.js @@ -17,6 +17,9 @@ limitations under the License. const Promise = require('bluebird'); const sanitize = require('sanitize-html'); + +const fileToDataUrl = require("./file-to-data-url"); + const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/; /** @@ -57,22 +60,6 @@ function awaitImageLoad(image) { }); } -function awaitFileReader(dataUrl) { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - - reader.onload = function(event) { - resolve(event.target.result); - }; - - reader.onerror = function(error) { - reject(error); - }; - - reader.readAsDataURL(dataUrl); - }); -} - function awaitVideoLoad(video) { return new Promise((resolve, reject) => { video.onloadeddata = function() { @@ -150,6 +137,8 @@ module.exports = { return awaitImageLoad(img); }).then(() => { URL.revokeObjectURL(objectUrl); + + return img; }); }); }, @@ -162,7 +151,7 @@ module.exports = { */ loadVideoElement: function(videoFile) { return Promise.try(() => { - return awaitFileReader(videoFile); + return fileToDataUrl(videoFile); }).then((url) => { const video = Object.assign(document.createElement("video"), { src: url diff --git a/src/lib/with-element.js b/src/lib/with-element.js new file mode 100644 index 0000000..e0084d1 --- /dev/null +++ b/src/lib/with-element.js @@ -0,0 +1,15 @@ +"use strict"; + +const React = require("react"); + +module.exports = function withElement(callback) { + let [ elementRef, setElementRef ] = React.useState(); + + React.useEffect(() => { + if (elementRef != null) { + callback(elementRef); + } + }, [ elementRef ]); + + return setElementRef; +};