Refactor state events and support showing joins
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Cadence Ember 2020-10-21 01:04:53 +13:00
parent c0cb857c07
commit 6b88ede18e
Signed by: cadence
GPG Key ID: BC1C2C61CF521B17
3 changed files with 63 additions and 17 deletions

View File

@ -43,6 +43,14 @@ class Event extends ElemJS {
this.update(data) this.update(data)
} }
// predicates
canGroup() {
return this.data.type === "m.room.message"
}
// operations
setGroup(group) { setGroup(group) {
this.group = group this.group = group
} }
@ -59,7 +67,17 @@ class Event extends ElemJS {
render() { render() {
this.element.classList[this.data.pending ? "add" : "remove"]("c-message--pending") this.element.classList[this.data.pending ? "add" : "remove"]("c-message--pending")
this.text(this.data.content.body) if (this.data.type === "m.room.message") {
this.text(this.data.content.body)
} else if (this.data.type === "m.room.member") {
if (this.data.content.membership === "join") {
this.child(ejs("i").text("joined the room"))
} else {
this.child(ejs("i").text("left the room"))
}
} else {
this.child(ejs("i").text(`Unsupported event type ${this.data.type}`))
}
} }
} }
@ -69,13 +87,19 @@ class Sender {
this.sender.subscribe("changeSelf", this.update.bind(this)) this.sender.subscribe("changeSelf", this.update.bind(this))
this.name = new ElemJS("div").class("c-message-group__name") this.name = new ElemJS("div").class("c-message-group__name")
this.avatar = new ElemJS("div").class("c-message-group__avatar") this.avatar = new ElemJS("div").class("c-message-group__avatar")
this.displayingGoodData = false
this.update() this.update()
} }
update() { update() {
if (this.sender.exists()) { if (this.sender.exists()) {
// name // name
this.name.text(this.sender.value().content.displayname) if (this.sender.value().content.displayname) {
this.name.text(this.sender.value().content.displayname)
this.displayingGoodData = true
} else if (!this.displayingGoodData) {
this.name.text(this.sender.value().state_key)
}
// avatar // avatar
this.avatar.clearChildren() this.avatar.clearChildren()
@ -181,7 +205,7 @@ class ReactiveTimeline extends ElemJS {
} }
class Timeline extends Subscribable { class Timeline extends Subscribable {
constructor(id) { constructor(room) {
super() super()
Object.assign(this.events, { Object.assign(this.events, {
beforeChange: [], beforeChange: [],
@ -191,25 +215,49 @@ class Timeline extends Subscribable {
beforeChange: [], beforeChange: [],
afterChange: [] afterChange: []
}) })
this.id = id this.room = room
this.id = this.room.id
this.list = [] this.list = []
this.map = new Map() this.map = new Map()
this.reactiveTimeline = new ReactiveTimeline(id, []) this.reactiveTimeline = new ReactiveTimeline(this.id, [])
this.latest = 0 this.latest = 0
this.pending = new Set() this.pending = new Set()
} }
updateStateEvents(events) {
for (const eventData of events) {
let id = eventData.event_id
if (eventData.type === "m.room.member") {
// update members
if (eventData.membership !== "leave") {
this.room.members.get(eventData.state_key).set(eventData)
}
}
}
}
updateEvents(events) { updateEvents(events) {
this.broadcast("beforeChange") this.broadcast("beforeChange")
// handle state events
this.updateStateEvents(events)
for (const eventData of events) { for (const eventData of events) {
// set variables
this.latest = Math.max(this.latest, eventData.origin_server_ts) this.latest = Math.max(this.latest, eventData.origin_server_ts)
let id = eventData.event_id let id = eventData.event_id
// handle local echoes
if (eventData.sender === lsm.get("mx_user_id") && eventData.content && this.pending.has(eventData.content["chat.carbon.message.pending_id"])) { if (eventData.sender === lsm.get("mx_user_id") && eventData.content && this.pending.has(eventData.content["chat.carbon.message.pending_id"])) {
id = eventData.content["chat.carbon.message.pending_id"] id = eventData.content["chat.carbon.message.pending_id"]
} }
// handle timeline events
if (this.map.has(id)) { if (this.map.has(id)) {
// update existing event
this.map.get(id).update(eventData) this.map.get(id).update(eventData)
} else { } else {
// skip displaying events that we don't know how to
if (eventData.type === "m.reaction") {
continue
}
// add new event
const event = new Event(eventData) const event = new Event(eventData)
this.map.set(id, event) this.map.set(id, event)
this.reactiveTimeline.addEvent(event) this.reactiveTimeline.addEvent(event)
@ -238,6 +286,7 @@ class Timeline extends Subscribable {
"chat.carbon.message.pending_id": id "chat.carbon.message.pending_id": id
} }
const fakeEvent = { const fakeEvent = {
type: "m.room.message",
origin_server_ts: Date.now(), origin_server_ts: Date.now(),
event_id: id, event_id: id,
sender: lsm.get("mx_user_id"), sender: lsm.get("mx_user_id"),

View File

@ -62,7 +62,7 @@ class Room extends ElemJS {
this.id = id this.id = id
this.data = data this.data = data
this.timeline = new Timeline(this.id) this.timeline = new Timeline(this)
this.group = null this.group = null
this.members = new SubscribeMapList(SubscribeValue) this.members = new SubscribeMapList(SubscribeValue)

View File

@ -47,19 +47,15 @@ function manageSync(root) {
} }
// set up rooms // set up rooms
Object.entries(root.rooms.join).forEach(([id, room]) => { Object.entries(root.rooms.join).forEach(([id, data]) => {
if (!store.rooms.has(id)) { if (!store.rooms.has(id)) {
store.rooms.askAdd(id, room) store.rooms.askAdd(id, data)
} }
const storeRoom = store.rooms.get(id).value() const room = store.rooms.get(id).value()
room.state.events.forEach(event => { const timeline = room.timeline
if (event.type === "m.room.member") { if (data.timeline.events.length) newEvents = true
storeRoom.members.get(event.state_key).set(event) timeline.updateStateEvents(data.state.events)
} timeline.updateEvents(data.timeline.events)
})
const timeline = storeRoom.timeline
if (room.timeline.events.length) newEvents = true
timeline.updateEvents(room.timeline.events)
}) })
// set up groups // set up groups
@ -90,6 +86,7 @@ function manageSync(root) {
store.rooms.get(groupRoom.room_id).value().setGroup(id) store.rooms.get(groupRoom.room_id).value().setGroup(id)
} }
}) })
store.newEvents.broadcast("changeSelf") // trigger a room list update
}) })
} }
}) })