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)
}
// predicates
canGroup() {
return this.data.type === "m.room.message"
}
// operations
setGroup(group) {
this.group = group
}
@ -59,7 +67,17 @@ class Event extends ElemJS {
render() {
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.name = new ElemJS("div").class("c-message-group__name")
this.avatar = new ElemJS("div").class("c-message-group__avatar")
this.displayingGoodData = false
this.update()
}
update() {
if (this.sender.exists()) {
// 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
this.avatar.clearChildren()
@ -181,7 +205,7 @@ class ReactiveTimeline extends ElemJS {
}
class Timeline extends Subscribable {
constructor(id) {
constructor(room) {
super()
Object.assign(this.events, {
beforeChange: [],
@ -191,25 +215,49 @@ class Timeline extends Subscribable {
beforeChange: [],
afterChange: []
})
this.id = id
this.room = room
this.id = this.room.id
this.list = []
this.map = new Map()
this.reactiveTimeline = new ReactiveTimeline(id, [])
this.reactiveTimeline = new ReactiveTimeline(this.id, [])
this.latest = 0
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) {
this.broadcast("beforeChange")
// handle state events
this.updateStateEvents(events)
for (const eventData of events) {
// set variables
this.latest = Math.max(this.latest, eventData.origin_server_ts)
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"])) {
id = eventData.content["chat.carbon.message.pending_id"]
}
// handle timeline events
if (this.map.has(id)) {
// update existing event
this.map.get(id).update(eventData)
} 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)
this.map.set(id, event)
this.reactiveTimeline.addEvent(event)
@ -238,6 +286,7 @@ class Timeline extends Subscribable {
"chat.carbon.message.pending_id": id
}
const fakeEvent = {
type: "m.room.message",
origin_server_ts: Date.now(),
event_id: id,
sender: lsm.get("mx_user_id"),

View File

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

View File

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