@@ 35,18 35,18 @@ var Workspace = Backbone.Router.extend({
sessionStorage.setItem('room_search', searchValue)
updateNavButton('chevron-left', 'back', '#')
- if (!document.getElementById(room)) {
- let roomDiv = el('div', { id: room })
+ if (!document.getElementById(esc(room))) {
+ let roomDiv = el('div', { id: esc(room) })
roomDiv.addEventListener('new_messages', e => { showRoom(room, e) })
roomDiv.addEventListener('new_image', e => {
document
- .getElementById(e.detail.id)
+ .getElementById(esc(e.detail.id))
.querySelector('.m_image')
.src = e.detail.image
})
getApp().appendChild(roomDiv)
}
- getApp().swapChild(room)
+ getApp().swapChild(esc(room))
getRoomHistory(room, 50)
showRoom(room)
@@ 101,7 101,7 @@ function makeRoomList() {
}
let template = document.querySelector('#templates #roomlist').cloneNode(true)
- template.id = `roomlist_${room.id}`
+ template.id = `roomlist_${esc(room.id)}`
template.href = `#room/${room.id}`
template.querySelector('.room-avatar').src = room.avatar.img
// TODO: find a better name for the room if we don't have a name or alias.
@@ 159,7 159,6 @@ function showRoom(room) {
// Group messages together if they're from the same sender.
if (prevSender != m.sender) {
- prevSender = m.sender
avatar = user.avatar.img
body = `
<strong>${user.name ?? ''}</strong> <small>${m.sender}</small>
@@ 197,10 196,6 @@ function showRoom(room) {
body += m.body
}
- if (m.edit) {
- body += ' (edited)'
- }
-
break
case 'm.image':
body += `
@@ 215,17 210,37 @@ function showRoom(room) {
continue
}
+ // If we have an edit, update the old message, don't insert one.
+ if (m.edit) {
+ // We don't have that message in our history.
+ // Discard the edit event for now.
+ if (!messageList.querySelector(`#${esc(m.edit)}`)) {
+ continue
+ }
+
+ // XXX: We're stomping the message header here. It needs to be it's own elem.
+ messageList
+ .querySelector(`#${esc(m.edit)} #message_body`)
+ .innerHTML = body + ' (edited)'
+
+ continue
+ }
+
let template = document.querySelector('#templates #message').cloneNode(true)
- template.id = m.event_id
- template.classList.add(m.sender)
+ template.id = esc(m.id)
+ template.classList.add(esc(m.sender))
template.querySelector('#message_body').innerHTML = body
if (avatar) { template.querySelector('.user-avatar').src = avatar }
template.appendTo(messageList)
+
+ // Don't update previous sender until the end.
+ // We may have an edit or other out of place event.
+ prevSender = m.sender
}
- document.getElementById(room).replaceChildren(messageList)
+ document.getElementById(esc(room)).replaceChildren(messageList)
// Scroll the viewport to the last message.
if (messageList.children.length) {
@@ 340,6 355,13 @@ function countMessages(room) {
return m
}
+// Escape a matrix identifier for use in HTML/CSS.
+// This is destructive, we can't go backwards.
+function esc(s) {
+ //return s.replace(/[#$@!:]/g, function(t) { return '\\' + t })
+ return s.replace(/[#$@!:.]/g, '_')
+}
+
// Main entry point
// ----------------
@@ 380,13 402,13 @@ document.addEventListener('DOMContentLoaded', e => {
if (!e.detail.id) {
// It's a room avatar.
document
- .getElementById('roomlist_' + e.detail.room)
+ .getElementById('roomlist_' + esc(e.detail.room))
.querySelector('.room-avatar')
.src = e.detail.avatar
} else {
// It's a user avatar for a specific room.
// TODO: Just do this globally for now, handle room avatars later.
- let messages = getApp().getElementsByClassName(e.detail.id)
+ let messages = getApp().getElementsByClassName(esc(e.detail.id))
for (m of messages) {
let a = m.querySelector('.user-avatar')
if (a.src) { a.src = e.detail.avatar }
@@ 230,6 230,9 @@ function parseMessageEvents(events, room) {
time: e.origin_server_ts,
sender: e.sender,
type: e.content.msgtype,
+ // For now we shove our room id inside the struct.
+ // This makes sorting by last activity easier.
+ id: e.event_id,
}
// TODO: We still want to sanitize the HTML and rewrite links.
@@ 439,7 442,7 @@ function sync() {
account.since = data.next_batch
// Let any rooms with active listeners know about new events.
- var roomElem = document.getElementById(room)
+ var roomElem = document.getElementById(esc(room))
if (roomElem) { roomElem.dispatchEvent(ev('new_messages', { dir: 'down' })) }
})
}
@@ 546,7 549,7 @@ function getRoomHistory(room, limit, prev) {
}
// Notify that we have new data.
- let roomElem = document.getElementById(room)
+ let roomElem = document.getElementById(esc(room))
if (roomElem) { roomElem.dispatchEvent(ev('new_messages', { dir: 'up' })) }
})
}