trying ot get the images to load

This commit is contained in:
Sharon Kennedy 2020-03-18 20:35:59 -04:00
parent 47d546a8d4
commit d8e482a689
6 changed files with 174 additions and 51 deletions

View File

@ -116,6 +116,8 @@
"webpack-serve": "3.2.0"
},
"dependencies": {
"browser-encrypt-attachment": "^0.3.0",
"isomorphic-fetch": "^2.2.1",
"linkifyjs": "^2.1.9",
"matrix-js-sdk": "^4.0.0",
"node-localstorage": "^2.1.5",

View File

@ -341,8 +341,11 @@ class ChatBox extends React.Component {
sender: event.getSender(),
roomId: event.getRoomId(),
content: event.getContent(),
}
console.log('message ===========>', message)
const messages = [...this.state.messages]
messages.push(message)
this.setState({ messages })
@ -479,7 +482,7 @@ class ChatBox extends React.Component {
{
messages.map((message, index) => {
return(
<Message key={message.id} message={message} userId={userId} botId={this.props.botUsername} />
<Message key={message.id} message={message} userId={userId} botId={this.props.botUsername} client={this.state.client} />
)
})
}

View File

@ -1,31 +1,53 @@
import React from "react"
import PropTypes from "prop-types"
import Linkify from 'linkifyjs/react';
import decryptFile from '../utils/decryptFile'
const Message = ({ message, userId, botId }) => {
const senderClass = () => {
switch (message.sender) {
class Message extends React.Component {
constructor(props) {
super(props);
this.state = {
decryptedUrl: null,
decryptedFile: null,
}
}
componentDidMount() {
const needsDecryption = ['m.file', 'm.image'];
if (needsDecryption.includes(this.props.message.content.msgtype)) {
decryptFile(this.props.message.content.file, this.props.client)
.then((decryptedBlob) => {
const decryptedUrl = URL.createObjectURL(decryptedBlob)
this.setState({
decryptedUrl: decryptedUrl,
decryptedBlob: decryptedBlob
})
})
}
}
componentWillUnmount() {
if (this.state.decryptedUrl) {
URL.revokeObjectURL(this.state.decryptedUrl);
}
}
senderClass = () => {
switch (this.props.message.sender) {
case 'from-me':
return 'from-me'
case userId:
case this.props.userId:
return 'from-me'
case botId:
case this.props.botId:
return 'from-bot'
default:
return 'from-support'
}
}
if (message.content.formatted_body) {
return (
<div className={`message ${senderClass()}`}>
<div className="text" dangerouslySetInnerHTML={{__html: message.content.formatted_body}} />
</div>
)
}
renderTextMessage = () => {
const linkifyOpts = {
linkAttributes: {
rel: 'noreferrer noopener',
@ -33,12 +55,59 @@ const Message = ({ message, userId, botId }) => {
}
return (
<div className={`message ${senderClass()}`}>
<div className={`message ${this.senderClass()}`}>
<div className="text">
<Linkify options={linkifyOpts}>{ message.content.body }</Linkify>
<Linkify options={linkifyOpts}>{ this.props.message.content.body }</Linkify>
</div>
</div>
)
}
renderHtmlMessage = () => {
return (
<div className={`message ${this.senderClass()}`}>
<div className="text" dangerouslySetInnerHTML={{__html: this.props.message.content.formatted_body}} />
</div>
)
}
renderImageMessage = () => {
return (
<div className={`message ${this.senderClass()}`}>
<div className="text">
<a href={this.state.decryptedUrl} target='_blank' rel='noopener noreferrer'>{ this.props.message.content.body }</a>
</div>
</div>
)
}
renderFileMessage = () => {
return (
<div className={`message ${this.senderClass()}`}>
<div className="text">
<a href={this.state.decryptedUrl} target='_blank' rel='noopener noreferrer'>{ this.props.message.content.body }</a>
</div>
</div>
)
}
render() {
console.log(this.props.message)
console.log(this.state)
const { message } = this.props;
switch(message.content.msgtype) {
case 'm.file':
return this.renderFileMessage()
case 'm.image':
return this.renderImageMessage()
default:
if (message.content.formatted_body) {
return this.renderHtmlMessage()
}
return this.renderTextMessage()
}
}
}
export default Message;

View File

@ -1,30 +0,0 @@
function checkFunc(dom, selector) {
if (typeof dom.update === 'function') {
const el = dom.update().find(selector);
if (el.exists()) {
return el;
}
return null;
}
const els = dom.querySelectorAll(selector);
if (els.length !== 0) {
return els;
}
return null;
}
export async function waitForSelection(dom, selector) {
let numSleep = 0;
for (;;) {
const el = checkFunc(dom, selector);
if (el) {
return el;
}
if (numSleep > 2) {
throw new Error(`could not find ${selector}`);
}
await new Promise(resolve => setTimeout(resolve, 250));
numSleep += 1;
}
}

46
src/utils/decryptFile.js Normal file
View File

@ -0,0 +1,46 @@
import encrypt from 'browser-encrypt-attachment';
import 'isomorphic-fetch';
const ALLOWED_BLOB_MIMETYPES = {
'image/jpeg': true,
'image/gif': true,
'image/png': true,
'video/mp4': true,
'video/webm': true,
'video/ogg': true,
'audio/mp4': true,
'audio/webm': true,
'audio/aac': true,
'audio/mpeg': true,
'audio/ogg': true,
'audio/wave': true,
'audio/wav': true,
'audio/x-wav': true,
'audio/x-pn-wav': true,
'audio/flac': true,
'audio/x-flac': true,
};
const decryptFile = (file, client) => {
const url = client.mxcUrlToHttp(file.url);
// Download the encrypted file as an array buffer.
return Promise.resolve(fetch(url))
.then((response) => response.arrayBuffer())
.then((responseData) => encrypt.decryptAttachment(responseData, file))
.then((dataArray) => {
// IMPORTANT: we must not allow scriptable mime-types into Blobs otherwise
// they introduce XSS attacks if the Blob URI is viewed directly in the
// browser (e.g. by copying the URI into a new tab or window.)
let mimetype = file.mimetype ? file.mimetype.split(';')[0].trim() : '';
if (!ALLOWED_BLOB_MIMETYPES[mimetype]) {
mimetype = 'application/octet-stream';
}
const blob = new Blob([dataArray], { type: mimetype });
return blob;
});
};
export default decryptFile;

View File

@ -3237,6 +3237,11 @@ brorand@^1.0.1:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
browser-encrypt-attachment@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/browser-encrypt-attachment/-/browser-encrypt-attachment-0.3.0.tgz#205a94caadf0dc7e81413941812f655bd190ff1c"
integrity sha1-IFqUyq3w3H6BQTlBgS9lW9GQ/xw=
browser-process-hrtime@^0.1.2:
version "0.1.3"
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
@ -4789,6 +4794,13 @@ encodeurl@^1.0.2, encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@ -6492,7 +6504,7 @@ humanize-url@^1.0.0:
normalize-url "^1.0.0"
strip-url-auth "^1.0.0"
iconv-lite@0.4.24, iconv-lite@^0.4.24:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -7051,7 +7063,7 @@ is-set@^2.0.1:
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43"
integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==
is-stream@^1.1.0:
is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
@ -7140,6 +7152,14 @@ isobject@^4.0.0:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
isomorphic-fetch@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@ -8653,6 +8673,14 @@ node-dir@^0.1.10:
dependencies:
minimatch "^3.0.2"
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-fetch@^2.3.0, node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
@ -12408,6 +12436,11 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
dependencies:
iconv-lite "0.4.24"
whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"