Member data and message dates

This commit is contained in:
Cadence Ember 2020-10-20 02:05:16 +13:00
parent 0e084c0a68
commit e13c4fdb00
Signed by untrusted user: cadence
GPG key ID: BC1C2C61CF521B17
9 changed files with 123 additions and 56 deletions

View file

@ -5,8 +5,8 @@
<link rel="stylesheet" type="text/css" href="static/main.css?static=f7c0898b94"> <link rel="stylesheet" type="text/css" href="static/main.css?static=f7c0898b94">
<script type="module" src="static/groups.js?static=2cc7f0daf8"></script> <script type="module" src="static/groups.js?static=2cc7f0daf8"></script>
<script type="module" src="static/chat-input.js?static=16321d4eb4"></script> <script type="module" src="static/chat-input.js?static=16321d4eb4"></script>
<script type="module" src="static/room-picker.js?static=46999be5e5"></script> <script type="module" src="static/room-picker.js?static=edb9a5f669"></script>
<script type="module" src="static/sync/sync.js?static=56e374b23d"></script> <script type="module" src="static/sync/sync.js?static=b817c21dbe"></script>
<script type="module" src="static/chat.js?static=fc121d3d23"></script> <script type="module" src="static/chat.js?static=fc121d3d23"></script>
<title>Carbon</title> <title>Carbon</title>
</head> </head>

View file

@ -1,7 +1,11 @@
import {ElemJS, ejs} from "./basic.js" import {ElemJS, ejs} from "./basic.js"
import {Subscribable} from "./store/Subscribable.js" import {Subscribable} from "./store/Subscribable.js"
import {store} from "./store/store.js"
import {Anchor} from "./Anchor.js" import {Anchor} from "./Anchor.js"
import * as lsm from "./lsm.js" import * as lsm from "./lsm.js"
import {resolveMxc} from "./functions.js"
const dateFormatter = Intl.DateTimeFormat("default", {hour: "numeric", minute: "numeric", second: "numeric", day: "numeric", month: "short", year: "numeric"})
let sentIndex = 0 let sentIndex = 0
@ -59,6 +63,35 @@ class Event extends ElemJS {
} }
} }
class Sender {
constructor(roomID, mxid) {
this.sender = store.rooms.get(roomID).value().members.get(mxid)
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.update()
}
update() {
if (this.sender.exists()) {
// name
this.name.text(this.sender.value().content.displayname)
// avatar
this.avatar.clearChildren()
if (this.sender.value().content.avatar_url) {
this.avatar.child(
ejs("img").class("c-message-group__icon").attribute("src", resolveMxc(this.sender.value().content.avatar_url, 32, "crop"))
)
} else {
this.avatar.child(
ejs("div").class("c-message-group__icon")
)
}
}
}
}
class EventGroup extends ElemJS { class EventGroup extends ElemJS {
constructor(reactive, list) { constructor(reactive, list) {
super("div") super("div")
@ -69,14 +102,13 @@ class EventGroup extends ElemJS {
sender: list[0].data.sender, sender: list[0].data.sender,
origin_server_ts: list[0].data.origin_server_ts origin_server_ts: list[0].data.origin_server_ts
} }
this.sender = new Sender(this.reactive.id, this.data.sender)
this.child( this.child(
ejs("div").class("c-message-group__avatar").child( this.sender.avatar,
ejs("div").class("c-message-group__icon")
),
this.messages = ejs("div").class("c-message-group__messages").child( this.messages = ejs("div").class("c-message-group__messages").child(
ejs("div").class("c-message-group__intro").child( ejs("div").class("c-message-group__intro").child(
ejs("div").class("c-message-group__name").text(this.data.sender), this.sender.name,
ejs("div").class("c-message-group__date").text(this.data.origin_server_ts) ejs("div").class("c-message-group__date").text(dateFormatter.format(this.data.origin_server_ts))
), ),
...this.list ...this.list
) )
@ -102,9 +134,10 @@ class EventGroup extends ElemJS {
} }
class ReactiveTimeline extends ElemJS { class ReactiveTimeline extends ElemJS {
constructor(list) { constructor(id, list) {
super("div") super("div")
this.class("c-event-groups") this.class("c-event-groups")
this.id = id
this.list = list this.list = list
this.render() this.render()
} }
@ -161,7 +194,7 @@ class Timeline extends Subscribable {
this.id = id this.id = id
this.list = [] this.list = []
this.map = new Map() this.map = new Map()
this.reactiveTimeline = new ReactiveTimeline([]) this.reactiveTimeline = new ReactiveTimeline(id, [])
this.latest = 0 this.latest = 0
this.pending = new Set() this.pending = new Set()
} }

View file

@ -1,16 +1,10 @@
import {q, ElemJS, ejs} from "./basic.js" import {q, ElemJS, ejs} from "./basic.js"
import {store} from "./store/store.js" import {store} from "./store/store.js"
import {SubscribeMapList} from "./store/SubscribeMapList.js"
import {SubscribeValue} from "./store/SubscribeValue.js"
import {Timeline} from "./Timeline.js" import {Timeline} from "./Timeline.js"
import * as lsm from "./lsm.js" import * as lsm from "./lsm.js"
import {resolveMxc} from "./functions.js"
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
if (size && method) {
return `${lsm.get("domain")}/_matrix/media/r0/thumbnail/${server}/${id}?width=${size}&height=${size}&method=${method}`
} else {
return `${lsm.get("domain")}/_matrix/media/r0/download/${server}/${id}`
}
}
class ActiveGroupMarker extends ElemJS { class ActiveGroupMarker extends ElemJS {
constructor() { constructor() {
@ -70,6 +64,7 @@ class Room extends ElemJS {
this.data = data this.data = data
this.timeline = new Timeline(this.id) this.timeline = new Timeline(this.id)
this.group = null this.group = null
this.members = new SubscribeMapList(SubscribeValue)
this.class("c-room") this.class("c-room")

View file

@ -1,18 +1,9 @@
import {store} from "../store/store.js" import {store} from "../store/store.js"
import * as lsm from "../lsm.js" import * as lsm from "../lsm.js"
import {resolveMxc} from "../functions.js"
let lastBatch = null let lastBatch = null
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
if (size && method) {
return `${lsm.get("domain")}/_matrix/media/r0/thumbnail/${server}/${id}?width=${size}&height=${size}&method=${method}`
} else {
return `${lsm.get("domain")}/_matrix/media/r0/download/${server}/${id}`
}
}
function sync() { function sync() {
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`) const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`)
url.searchParams.append("access_token", lsm.get("access_token")) url.searchParams.append("access_token", lsm.get("access_token"))
@ -60,7 +51,13 @@ function manageSync(root) {
if (!store.rooms.has(id)) { if (!store.rooms.has(id)) {
store.rooms.askAdd(id, room) store.rooms.askAdd(id, room)
} }
const timeline = store.rooms.get(id).value().timeline 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 if (room.timeline.events.length) newEvents = true
timeline.updateEvents(room.timeline.events) timeline.updateEvents(room.timeline.events)
}) })

View file

@ -79,6 +79,11 @@ module.exports = [
source: "/js/chat.js", source: "/js/chat.js",
target: "/static/chat.js" target: "/static/chat.js"
}, },
{
type: "js",
source: "/js/functions.js",
target: "/static/functions.js"
},
{ {
type: "file", type: "file",
source: "/assets/fonts/whitney-500.woff", source: "/assets/fonts/whitney-500.woff",

View file

@ -1,7 +1,11 @@
import {ElemJS, ejs} from "./basic.js" import {ElemJS, ejs} from "./basic.js"
import {Subscribable} from "./store/Subscribable.js" import {Subscribable} from "./store/Subscribable.js"
import {store} from "./store/store.js"
import {Anchor} from "./Anchor.js" import {Anchor} from "./Anchor.js"
import * as lsm from "./lsm.js" import * as lsm from "./lsm.js"
import {resolveMxc} from "./functions.js"
const dateFormatter = Intl.DateTimeFormat("default", {hour: "numeric", minute: "numeric", second: "numeric", day: "numeric", month: "short", year: "numeric"})
let sentIndex = 0 let sentIndex = 0
@ -59,6 +63,35 @@ class Event extends ElemJS {
} }
} }
class Sender {
constructor(roomID, mxid) {
this.sender = store.rooms.get(roomID).value().members.get(mxid)
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.update()
}
update() {
if (this.sender.exists()) {
// name
this.name.text(this.sender.value().content.displayname)
// avatar
this.avatar.clearChildren()
if (this.sender.value().content.avatar_url) {
this.avatar.child(
ejs("img").class("c-message-group__icon").attribute("src", resolveMxc(this.sender.value().content.avatar_url, 32, "crop"))
)
} else {
this.avatar.child(
ejs("div").class("c-message-group__icon")
)
}
}
}
}
class EventGroup extends ElemJS { class EventGroup extends ElemJS {
constructor(reactive, list) { constructor(reactive, list) {
super("div") super("div")
@ -69,14 +102,13 @@ class EventGroup extends ElemJS {
sender: list[0].data.sender, sender: list[0].data.sender,
origin_server_ts: list[0].data.origin_server_ts origin_server_ts: list[0].data.origin_server_ts
} }
this.sender = new Sender(this.reactive.id, this.data.sender)
this.child( this.child(
ejs("div").class("c-message-group__avatar").child( this.sender.avatar,
ejs("div").class("c-message-group__icon")
),
this.messages = ejs("div").class("c-message-group__messages").child( this.messages = ejs("div").class("c-message-group__messages").child(
ejs("div").class("c-message-group__intro").child( ejs("div").class("c-message-group__intro").child(
ejs("div").class("c-message-group__name").text(this.data.sender), this.sender.name,
ejs("div").class("c-message-group__date").text(this.data.origin_server_ts) ejs("div").class("c-message-group__date").text(dateFormatter.format(this.data.origin_server_ts))
), ),
...this.list ...this.list
) )
@ -102,9 +134,10 @@ class EventGroup extends ElemJS {
} }
class ReactiveTimeline extends ElemJS { class ReactiveTimeline extends ElemJS {
constructor(list) { constructor(id, list) {
super("div") super("div")
this.class("c-event-groups") this.class("c-event-groups")
this.id = id
this.list = list this.list = list
this.render() this.render()
} }
@ -161,7 +194,7 @@ class Timeline extends Subscribable {
this.id = id this.id = id
this.list = [] this.list = []
this.map = new Map() this.map = new Map()
this.reactiveTimeline = new ReactiveTimeline([]) this.reactiveTimeline = new ReactiveTimeline(id, [])
this.latest = 0 this.latest = 0
this.pending = new Set() this.pending = new Set()
} }

12
src/js/functions.js Normal file
View file

@ -0,0 +1,12 @@
import * as lsm from "./lsm.js"
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
if (size && method) {
return `${lsm.get("domain")}/_matrix/media/r0/thumbnail/${server}/${id}?width=${size}&height=${size}&method=${method}`
} else {
return `${lsm.get("domain")}/_matrix/media/r0/download/${server}/${id}`
}
}
export {resolveMxc}

View file

@ -1,16 +1,10 @@
import {q, ElemJS, ejs} from "./basic.js" import {q, ElemJS, ejs} from "./basic.js"
import {store} from "./store/store.js" import {store} from "./store/store.js"
import {SubscribeMapList} from "./store/SubscribeMapList.js"
import {SubscribeValue} from "./store/SubscribeValue.js"
import {Timeline} from "./Timeline.js" import {Timeline} from "./Timeline.js"
import * as lsm from "./lsm.js" import * as lsm from "./lsm.js"
import {resolveMxc} from "./functions.js"
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
if (size && method) {
return `${lsm.get("domain")}/_matrix/media/r0/thumbnail/${server}/${id}?width=${size}&height=${size}&method=${method}`
} else {
return `${lsm.get("domain")}/_matrix/media/r0/download/${server}/${id}`
}
}
class ActiveGroupMarker extends ElemJS { class ActiveGroupMarker extends ElemJS {
constructor() { constructor() {
@ -70,6 +64,7 @@ class Room extends ElemJS {
this.data = data this.data = data
this.timeline = new Timeline(this.id) this.timeline = new Timeline(this.id)
this.group = null this.group = null
this.members = new SubscribeMapList(SubscribeValue)
this.class("c-room") this.class("c-room")

View file

@ -1,18 +1,9 @@
import {store} from "../store/store.js" import {store} from "../store/store.js"
import * as lsm from "../lsm.js" import * as lsm from "../lsm.js"
import {resolveMxc} from "../functions.js"
let lastBatch = null let lastBatch = null
function resolveMxc(url, size, method) {
const [server, id] = url.match(/^mxc:\/\/([^/]+)\/(.*)/).slice(1)
if (size && method) {
return `${lsm.get("domain")}/_matrix/media/r0/thumbnail/${server}/${id}?width=${size}&height=${size}&method=${method}`
} else {
return `${lsm.get("domain")}/_matrix/media/r0/download/${server}/${id}`
}
}
function sync() { function sync() {
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`) const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`)
url.searchParams.append("access_token", lsm.get("access_token")) url.searchParams.append("access_token", lsm.get("access_token"))
@ -60,7 +51,13 @@ function manageSync(root) {
if (!store.rooms.has(id)) { if (!store.rooms.has(id)) {
store.rooms.askAdd(id, room) store.rooms.askAdd(id, room)
} }
const timeline = store.rooms.get(id).value().timeline 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 if (room.timeline.events.length) newEvents = true
timeline.updateEvents(room.timeline.events) timeline.updateEvents(room.timeline.events)
}) })