displaying replies nicely

master
f0x 6 years ago
parent 2cb8008624
commit 172fd44dd5

@ -99,7 +99,7 @@ let chat = create({
messageGroups.groups.push(messageGroups.current)
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
@ -145,7 +145,7 @@ let EventGroup = create({
render: function() {
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">
{this.state.avatar}

@ -4,34 +4,83 @@ const ReactDOM = require('react-dom')
const create = require('create-react-class')
const defaultValue = require('default-value')
const riot = require('../../lib/riot-utils.js')
const elements = {
"m.text": require('./text.js'),
"m.image": require('./image.js')
}
const mxReplyRegex = /<mx-reply>(.+)<\/mx-reply>/
let Event = create({
displayName: "Event",
render: function() {
let event = this.props.event
let state = ""
let reply = ""
let element = "unsupported event"
if (this.props.event.local) {
if (event.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 (
<div className={"event" + state}>
{getRenderedEvent(this.props.event, this.props.client)}
{reply}
{element}
</div>
)
}
})
function getRenderedEvent(event, client) {
if (event.type == "m.room.message") {
let msgtype = event.content.msgtype;
return React.createElement(defaultValue(elements[msgtype], elements["m.text"]), {event: event, client: client})
function getEvent(event) {
let body = event.content.body
if (event.content.format == "org.matrix.custom.html") {
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

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

@ -15,20 +15,20 @@ let Event = create({
let eventBody
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
className={this.props.nested ? "nested" : "body"}
dangerouslySetInnerHTML={{__html: html}}
dangerouslySetInnerHTML={{__html: this.props.body}}
/>
} else {
eventBody =
<div className={this.props.nested ? "nested" : "body"}>
{event.content.body}
{this.props.body}
</div>
}
let eventClass = "event"
let eventClass = ""
if (event.local) {
eventClass += " local"
}

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

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

Loading…
Cancel
Save