121 lines
2.5 KiB
JavaScript
121 lines
2.5 KiB
JavaScript
|
const {ElemJS, ejs} = require("./basic.js")
|
||
|
const {store} = require("./store/store.js")
|
||
|
const {resolveMxc} = require("./functions.js")
|
||
|
|
||
|
function nameToColor(str) {
|
||
|
// code from element's react sdk
|
||
|
const colors = ["#55a7f0", "#da55ff", "#1bc47c", "#ea657e", "#fd8637", "#22cec6", "#8c8de3", "#71bf22"]
|
||
|
let hash = 0
|
||
|
let i
|
||
|
let chr
|
||
|
if (str.length === 0) {
|
||
|
return hash
|
||
|
}
|
||
|
for (i = 0; i < str.length; i++) {
|
||
|
chr = str.charCodeAt(i)
|
||
|
hash = ((hash << 5) - hash) + chr
|
||
|
hash |= 0
|
||
|
}
|
||
|
hash = Math.abs(hash) % 8
|
||
|
return colors[hash]
|
||
|
}
|
||
|
|
||
|
class Avatar extends ElemJS {
|
||
|
constructor() {
|
||
|
super("div")
|
||
|
this.class("c-message-group__avatar")
|
||
|
|
||
|
this.mxc = undefined
|
||
|
this.image = null
|
||
|
|
||
|
this.update(null)
|
||
|
}
|
||
|
|
||
|
update(mxc) {
|
||
|
if (mxc === this.mxc) return
|
||
|
this.mxc = mxc
|
||
|
this.hasImage = !!mxc
|
||
|
if (this.hasImage) {
|
||
|
const size = 96
|
||
|
const url = resolveMxc(mxc, size, "crop")
|
||
|
this.image = ejs("img").class("c-message-group__icon").attribute("src", url).attribute("width", size).attribute("height", size)
|
||
|
this.image.on("error", this.onError.bind(this))
|
||
|
}
|
||
|
this.render()
|
||
|
}
|
||
|
|
||
|
onError() {
|
||
|
this.hasImage = false
|
||
|
this.render()
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
this.clearChildren()
|
||
|
if (this.hasImage) {
|
||
|
this.child(this.image)
|
||
|
} else {
|
||
|
this.child(
|
||
|
ejs("div").class("c-message-group__icon", "c-message-group__icon--no-icon")
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Must update at least once to render. */
|
||
|
class Name extends ElemJS {
|
||
|
constructor() {
|
||
|
super("div")
|
||
|
this.class("c-message-group__name")
|
||
|
|
||
|
/**
|
||
|
* Keeps track of whether we have the proper display name or not.
|
||
|
* If we do, then we shoudn't override it with the mxid if the name becomes unavailable.
|
||
|
*/
|
||
|
this.hasName = false
|
||
|
this.name = ""
|
||
|
this.mxid = ""
|
||
|
}
|
||
|
|
||
|
update(event) {
|
||
|
this.mxid = event.state_key
|
||
|
if (event.content.displayname) {
|
||
|
this.hasName = true
|
||
|
this.name = event.content.displayname
|
||
|
} else if (!this.hasName) {
|
||
|
this.name = this.mxid
|
||
|
}
|
||
|
this.render()
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
// set text
|
||
|
this.text(this.name)
|
||
|
// set color
|
||
|
this.style("color", nameToColor(this.mxid))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Sender {
|
||
|
constructor(roomID, mxid) {
|
||
|
this.sender = store.rooms.get(roomID).value().members.get(mxid)
|
||
|
this.name = new Name()
|
||
|
this.avatar = new Avatar()
|
||
|
this.sender.subscribe("changeSelf", this.update.bind(this))
|
||
|
this.update()
|
||
|
}
|
||
|
|
||
|
update() {
|
||
|
if (this.sender.exists()) {
|
||
|
// name
|
||
|
this.name.update(this.sender.value())
|
||
|
|
||
|
// avatar
|
||
|
this.avatar.update(this.sender.value().content.avatar_url)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
Sender
|
||
|
}
|