displaying replies nicely

master
f0x 5 years ago
parent 2cb8008624
commit 172fd44dd5

@ -99,7 +99,7 @@ let chat = create({
messageGroups.groups.push(messageGroups.current) messageGroups.groups.push(messageGroups.current)
events = messageGroups.groups.map((events, id) => { events = messageGroups.groups.map((events, id) => {
return <EventGroup key={`${this.props.roomId}-${id}`} events={events} client={this.props.client}/> return <EventGroup key={`${this.props.roomId}-${id}`} events={events} client={this.props.client} room={room}/>
}) })
} }
//TODO: replace with something that only renders events in view //TODO: replace with something that only renders events in view
@ -145,7 +145,7 @@ let EventGroup = create({
render: function() { render: function() {
let events = this.props.events.map((event, key) => { let events = this.props.events.map((event, key) => {
return <Event event={event} key={key} client={this.props.client} /> return <Event event={event} key={key} client={this.props.client} room={this.props.room} />
}) })
return <div className="eventGroup"> return <div className="eventGroup">
{this.state.avatar} {this.state.avatar}

@ -4,34 +4,83 @@ const ReactDOM = require('react-dom')
const create = require('create-react-class') const create = require('create-react-class')
const defaultValue = require('default-value') const defaultValue = require('default-value')
const riot = require('../../lib/riot-utils.js')
const elements = { const elements = {
"m.text": require('./text.js'), "m.text": require('./text.js'),
"m.image": require('./image.js') "m.image": require('./image.js')
} }
const mxReplyRegex = /<mx-reply>(.+)<\/mx-reply>/
let Event = create({ let Event = create({
displayName: "Event", displayName: "Event",
render: function() { render: function() {
let event = this.props.event
let state = "" let state = ""
let reply = ""
let element = "unsupported event"
if (this.props.event.local) { if (event.local) {
state = " local" state = " local"
} }
if (event.type == "m.room.message") {
let msgtype = event.content.msgtype;
let formattedEvent = getEvent(event)
let parsedBody = formattedEvent.body
let parsedReply = formattedEvent.parsedReply
if (parsedReply.isReply) {
let repliedEvent = this.props.room.findEventById(parsedReply.to)
let shortText = getEvent(repliedEvent.event).body
if (shortText.length > 50) {
shortText = shortText.substr(0, 50) + "..."
}
reply = (
<div className="reply">
{shortText}
</div>
)
}
element = React.createElement(defaultValue(elements[msgtype], elements["m.text"]), {body: parsedBody, event: event, client: this.props.client})
}
return ( return (
<div className={"event" + state}> <div className={"event" + state}>
{getRenderedEvent(this.props.event, this.props.client)} {reply}
{element}
</div> </div>
) )
} }
}) })
function getRenderedEvent(event, client) { function getEvent(event) {
if (event.type == "m.room.message") { let body = event.content.body
let msgtype = event.content.msgtype; if (event.content.format == "org.matrix.custom.html") {
return React.createElement(defaultValue(elements[msgtype], elements["m.text"]), {event: event, client: client}) body = riot.sanitize(event.content.formatted_body)
}
let parsedReply = parseReply(event, body)
if (parsedReply.isReply) {
body = parsedReply.body
}
return {body: body, parsedReply: parsedReply}
}
function parseReply(event, body) {
let replyTo
try {
replyTo = event.content['m.relates_to']['m.in_reply_to'].event_id
if (replyTo) {
// strip <mx-reply> from message if it exists
body = body.replace(mxReplyRegex, "")
}
} catch(err) {
// no reply
return {isReply: false}
} }
return {isReply: true, body: body, to: replyTo}
} }
module.exports = Event module.exports = Event

@ -28,14 +28,14 @@ let Event = create({
}, },
render: function() { render: function() {
return <div className="event"> return (
<div className="body"> <div className="body">
<a href={this.state.url.media} target="_blank"> <a href={this.state.url.media} target="_blank">
<img src={this.state.url.thumb}/> <img src={this.state.url.thumb}/>
</a> </a>
<Text event={this.props.event} nested={true}/> <Text event={this.props.event} nested={true}/>
</div> </div>
</div> )
} }
}) })

@ -15,20 +15,20 @@ let Event = create({
let eventBody let eventBody
if (event.content.format == "org.matrix.custom.html") { if (event.content.format == "org.matrix.custom.html") {
let html = riot.sanitize(event.content.formatted_body) //let html = riot.sanitize(event.content.formatted_body)
eventBody = <div eventBody = <div
className={this.props.nested ? "nested" : "body"} className={this.props.nested ? "nested" : "body"}
dangerouslySetInnerHTML={{__html: html}} dangerouslySetInnerHTML={{__html: this.props.body}}
/> />
} else { } else {
eventBody = eventBody =
<div className={this.props.nested ? "nested" : "body"}> <div className={this.props.nested ? "nested" : "body"}>
{event.content.body} {this.props.body}
</div> </div>
} }
let eventClass = "event" let eventClass = ""
if (event.local) { if (event.local) {
eventClass += " local" eventClass += " local"
} }

@ -4,6 +4,7 @@ const ReactDOM = require('react-dom')
const create = require('create-react-class') const create = require('create-react-class')
const Promise = require('bluebird') const Promise = require('bluebird')
const colorConvert = require('color-convert') const colorConvert = require('color-convert')
const sanitize = require('sanitize-html')
let input = create({ let input = create({
displayName: "Input", displayName: "Input",
@ -77,7 +78,7 @@ let input = create({
sendHTML: function(html) { sendHTML: function(html) {
let content = { let content = {
body: html, // this should probably be stripped to plaintext body: sanitize(html, {allowedTags: []}),
formatted_body: html, formatted_body: html,
format: "org.matrix.custom.html", format: "org.matrix.custom.html",
msgtype: "m.text" msgtype: "m.text"
@ -99,8 +100,8 @@ function handleCommands(command, parts) {
if (parts.length < 2) { if (parts.length < 2) {
return return
} }
let string = "" let string = parts[1]
for(let i=1; i < parts.length; i++) { for(let i=2; i < parts.length; i++) {
string += " " + parts[i] string += " " + parts[i]
} }
let html = rainbowTransform(string) let html = rainbowTransform(string)

@ -276,7 +276,6 @@ body {
#name { #name {
font-weight: bold; font-weight: bold;
padding-left: $spacing/2;
} }
#avatar { #avatar {
@ -298,26 +297,41 @@ body {
grid-area: content; grid-area: content;
padding-left: $spacing * 1.2; padding-left: $spacing * 1.2;
.local { .reply + .event {
color: $bg4; margin-bottom: $spacing;
} }
.body { .event {
padding: $spacing/4; .reply {
padding-left: $spacing/2; border-left: $borderwidth solid $blue;
white-space: pre-wrap; padding-left: 1/2 * $spacing;
margin-top: $spacing;
}
img { &:nth-child(2) .reply {
max-height: 40vh; margin-top: 0;
max-width: 90%; }
object-fit: contain;
.body {
padding: $spacing/4 0;
white-space: pre-wrap;
img {
max-height: 40vh;
max-width: 90%;
object-fit: contain;
}
}
&:hover {
border-radius: 0.1rem;
background-color: hsla(0, 100%, 100%, 0.05);
transition: 0.1s;
} }
}
.body:hover { & .local {
border-radius: 0.1rem; color: $bg4;
background-color: hsla(0, 100%, 100%, 0.05); }
transition: 0.1s;
} }
} }
} }

Loading…
Cancel
Save