linkify messages

This commit is contained in:
Sharon Kennedy 2020-03-15 00:47:19 -04:00
parent 54d4980e84
commit 47d546a8d4
7 changed files with 89 additions and 28 deletions

View File

@ -116,6 +116,7 @@
"webpack-serve": "3.2.0" "webpack-serve": "3.2.0"
}, },
"dependencies": { "dependencies": {
"linkifyjs": "^2.1.9",
"matrix-js-sdk": "^4.0.0", "matrix-js-sdk": "^4.0.0",
"node-localstorage": "^2.1.5", "node-localstorage": "^2.1.5",
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz", "olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",

View File

@ -30,6 +30,7 @@
right: 10px; right: 10px;
z-index: 9999; z-index: 9999;
width: 400px; width: 400px;
max-width: 100vw;
} }
.dock { .dock {
@ -323,6 +324,14 @@
margin-left: 10%; margin-left: 10%;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
} }
a {
color: $white;
&:hover, &:focus {
color: $light-purple;
}
}
} }
&.from-support { &.from-support {
@ -337,6 +346,14 @@
margin-right: 10%; margin-right: 10%;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
} }
a {
color: $dark-color;
&:hover, &:focus {
color: $medium-purple;
}
}
} }
} }

View File

@ -85,6 +85,34 @@
color: $light-text-color; color: $light-text-color;
border: 1px solid $dark-theme-color; border: 1px solid $dark-theme-color;
} }
a {
color: $light-text-color;
&:hover, &:focus {
color: $light-purple;
}
}
}
.buttons {
button {
background-color: transparent;
border: 1px solid $theme-color;
&:hover {
border: 1px solid $light-purple;
box-shadow: inset 0px 0px 0px 1px $light-purple;
}
&:focus {
outline: none;
color: $white;
border: 1px solid $light-purple;
box-shadow: inset 0px 0px 0px 1px $light-purple;
background-color: $dark-theme-highlight-color;
}
}
} }
} }

View File

@ -174,7 +174,6 @@ class ChatBox extends React.Component {
userId: data.user_id, userId: data.user_id,
deviceId: data.device_id, deviceId: data.device_id,
sessionStore: new matrix.WebStorageSessionStore(localStorage), sessionStore: new matrix.WebStorageSessionStore(localStorage),
displayName: this.props.anonymousDisplayName,
} }
client = matrix.createClient(opts) client = matrix.createClient(opts)
@ -184,6 +183,7 @@ class ChatBox extends React.Component {
}) })
.then(() => client.initCrypto()) .then(() => client.initCrypto())
.catch(err => this.initializeUnencryptedChat()) .catch(err => this.initializeUnencryptedChat())
.then(() => client.setDisplayName(this.props.anonymousDisplayName))
.then(() => client.startClient()) .then(() => client.startClient())
.then(() => { .then(() => {
this.setState({ this.setState({
@ -202,12 +202,12 @@ class ChatBox extends React.Component {
accessToken: this.state.accessToken, accessToken: this.state.accessToken,
userId: this.state.userId, userId: this.state.userId,
deviceId: this.state.deviceId, deviceId: this.state.deviceId,
displayName: this.props.anonymousDisplayName,
} }
let client; let client;
try { try {
client = matrix.createClient(opts) client = matrix.createClient(opts)
client.setDisplayName(this.props.anonymousDisplayName)
} catch { } catch {
return this.handleInitError() return this.handleInitError()
} }
@ -287,12 +287,8 @@ class ChatBox extends React.Component {
}) })
} }
sendMessage = () => { sendMessage = (message) => {
this.state.client.sendTextMessage(this.state.roomId, this.state.inputValue) this.state.client.sendTextMessage(this.state.roomId, message)
.then((res) => {
this.setState({ inputValue: "" })
this.chatboxInput.current.focus()
})
.catch((err) => { .catch((err) => {
switch (err["name"]) { switch (err["name"]) {
case "UnknownDeviceError": case "UnknownDeviceError":
@ -301,9 +297,10 @@ class ChatBox extends React.Component {
this.state.client.setDeviceKnown(userId, deviceId, true); this.state.client.setDeviceKnown(userId, deviceId, true);
}); });
}); });
this.sendMessage() this.sendMessage(message)
break; break;
default: default:
this.displayBotMessage({ body: "Your message was not sent." })
console.log("Error sending message", err); console.log("Error sending message", err);
} }
}) })
@ -434,10 +431,13 @@ class ChatBox extends React.Component {
handleSubmit = e => { handleSubmit = e => {
e.preventDefault() e.preventDefault()
if (!Boolean(this.state.inputValue)) return null; const message = this.state.inputValue
if (!Boolean(message)) return null;
if (this.state.client && this.state.roomId) { if (this.state.client && this.state.roomId) {
return this.sendMessage() this.setState({ inputValue: "" })
this.chatboxInput.current.focus()
return this.sendMessage(message)
} }
} }
@ -461,7 +461,7 @@ class ChatBox extends React.Component {
</div> </div>
<div className={`message from-bot`}> <div className={`message from-bot`}>
<div className="text">Please read the full <a href={this.props.termsUrl} ref={this.termsUrl}>terms and conditions</a>. By using this chat, you agree to these terms.</div> <div className="text">Please read the full <a href={this.props.termsUrl} ref={this.termsUrl} target='_blank' rel='noopener noreferrer'>terms and conditions</a>. By using this chat, you agree to these terms.</div>
</div> </div>
<div className={`message from-bot`}> <div className={`message from-bot`}>
@ -471,8 +471,8 @@ class ChatBox extends React.Component {
<div className={`message from-bot`}> <div className={`message from-bot`}>
<div className="text buttons"> <div className="text buttons">
{`👉`} {`👉`}
<button id="accept" onClick={this.handleAcceptTerms}>YES</button> <button className="btn" id="accept" onClick={this.handleAcceptTerms}>YES</button>
<button id="reject" onClick={this.handleRejectTerms}>NO</button> <button className="btn" id="reject" onClick={this.handleRejectTerms}>NO</button>
</div> </div>
</div> </div>

View File

@ -1,5 +1,6 @@
import React from "react" import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import Linkify from 'linkifyjs/react';
const Message = ({ message, userId, botId }) => { const Message = ({ message, userId, botId }) => {
@ -16,6 +17,7 @@ const Message = ({ message, userId, botId }) => {
} }
} }
if (message.content.formatted_body) { if (message.content.formatted_body) {
return ( return (
<div className={`message ${senderClass()}`}> <div className={`message ${senderClass()}`}>
@ -24,9 +26,17 @@ const Message = ({ message, userId, botId }) => {
) )
} }
const linkifyOpts = {
linkAttributes: {
rel: 'noreferrer noopener',
},
}
return ( return (
<div className={`message ${senderClass()}`}> <div className={`message ${senderClass()}`}>
<div className="text">{ message.content.body }</div> <div className="text">
<Linkify options={linkifyOpts}>{ message.content.body }</Linkify>
</div>
</div> </div>
) )
} }

View File

@ -1,12 +1,6 @@
import EmbeddableChatbox from './embeddable-chatbox'; import EmbeddableChatbox from './embeddable-chatbox';
export default function bookmarklet() { const config = {
if (window.EmbeddableChatbox) {
return;
}
window.EmbeddableChatbox = EmbeddableChatbox;
var config = {
matrixServerUrl: 'https://matrix.rhok.space', matrixServerUrl: 'https://matrix.rhok.space',
botUsername: '@help-bot:rhok.space', botUsername: '@help-bot:rhok.space',
roomName: 'Support Chat', roomName: 'Support Chat',
@ -17,7 +11,13 @@ export default function bookmarklet() {
exitMessage: 'The chat was not started.', exitMessage: 'The chat was not started.',
chatUnavailableMessage: 'The chat service is not available right now. Please try again later.', chatUnavailableMessage: 'The chat service is not available right now. Please try again later.',
anonymousDisplayName: 'Anonymous', anonymousDisplayName: 'Anonymous',
};
export default function bookmarklet() {
if (window.EmbeddableChatbox) {
return;
} }
window.EmbeddableChatbox = EmbeddableChatbox;
EmbeddableChatbox.mount(config); EmbeddableChatbox.mount(config);
} }

View File

@ -7950,6 +7950,11 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
linkifyjs@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.9.tgz#af06e45a2866ff06c4766582590d098a4d584702"
integrity sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==
load-json-file@^1.0.0: load-json-file@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"