forked from cadence/Carbon
Member data and message dates
This commit is contained in:
parent
0e084c0a68
commit
e13c4fdb00
9 changed files with 123 additions and 56 deletions
|
@ -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>
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
5
spec.js
5
spec.js
|
@ -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",
|
||||||
|
|
|
@ -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
12
src/js/functions.js
Normal 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}
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue