forked from cadence/Carbon
Support Element's groups and list sorting
This commit is contained in:
parent
4b0b5c4b39
commit
1f9462b89d
18 changed files with 272 additions and 145 deletions
2
build.js
2
build.js
|
@ -49,7 +49,7 @@ function validate(filename, body, type) {
|
|||
let match
|
||||
if (match = message.message.match(/Property “([\w-]+)” doesn't exist.$/)) {
|
||||
// allow these properties specifically
|
||||
if (["scrollbar-width", "scrollbar-color"].includes(match[1])) {
|
||||
if (["scrollbar-width", "scrollbar-color", "overflow-anchor"].includes(match[1])) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="static/main.css?static=da499eb39c">
|
||||
<link rel="stylesheet" type="text/css" href="static/main.css?static=9aad8398d2">
|
||||
<script type="module" src="static/groups.js?static=2cc7f0daf8"></script>
|
||||
<script type="module" src="static/chat-input.js?static=e8b21037fa"></script>
|
||||
<script type="module" src="static/room-picker.js?static=1d38378110"></script>
|
||||
<script type="module" src="static/sync/sync.js?static=9e31c8a727"></script>
|
||||
<script type="module" src="static/room-picker.js?static=7bc94b38d3"></script>
|
||||
<script type="module" src="static/sync/sync.js?static=56e374b23d"></script>
|
||||
<script type="module" src="static/chat.js?static=8a04bee48d"></script>
|
||||
<title>Carbon</title>
|
||||
</head>
|
||||
|
|
|
@ -7,7 +7,7 @@ class Anchor extends ElemJS {
|
|||
}
|
||||
|
||||
scroll() {
|
||||
console.log("anchor scrolled")
|
||||
// console.log("anchor scrolled")
|
||||
this.element.scrollIntoView({block: "start"})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ class EventGroup extends ElemJS {
|
|||
this.messages = ejs("div").class("c-message-group__messages").child(
|
||||
ejs("div").class("c-message-group__intro").child(
|
||||
ejs("div").class("c-message-group__name").text(this.data.sender),
|
||||
ejs("div").class("c-message-group__date").text("at 4:20 pm")
|
||||
ejs("div").class("c-message-group__date").text(this.data.origin_server_ts)
|
||||
),
|
||||
...this.list
|
||||
)
|
||||
|
@ -123,11 +123,13 @@ class Timeline extends Subscribable {
|
|||
this.list = []
|
||||
this.map = new Map()
|
||||
this.reactiveTimeline = new ReactiveTimeline([])
|
||||
this.latest = 0
|
||||
}
|
||||
|
||||
updateEvents(events) {
|
||||
this.broadcast("beforeChange")
|
||||
for (const eventData of events) {
|
||||
this.latest = Math.max(this.latest, eventData.origin_server_ts)
|
||||
if (this.map.has(eventData.event_id)) {
|
||||
this.map.get(eventData.event_id).update(eventData)
|
||||
} else {
|
||||
|
|
|
@ -71,7 +71,7 @@ body {
|
|||
position: relative;
|
||||
width: 80px;
|
||||
flex-shrink: 0;
|
||||
font-size: 24px;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.c-groups__display {
|
||||
|
|
|
@ -36,6 +36,7 @@ class Group extends ElemJS {
|
|||
super("div")
|
||||
|
||||
this.data = data
|
||||
this.order = this.data.order
|
||||
|
||||
this.class("c-group")
|
||||
this.child(
|
||||
|
@ -68,6 +69,7 @@ class Room extends ElemJS {
|
|||
this.id = id
|
||||
this.data = data
|
||||
this.timeline = new Timeline()
|
||||
this.group = null
|
||||
|
||||
this.class("c-room")
|
||||
|
||||
|
@ -77,6 +79,25 @@ class Room extends ElemJS {
|
|||
this.render()
|
||||
}
|
||||
|
||||
get order() {
|
||||
if (this.group) {
|
||||
let chars = 36
|
||||
let total = 0
|
||||
const name = this.getName()
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
const c = name[i]
|
||||
let d = 0
|
||||
if (c >= "A" && c <= "Z") d = c.charCodeAt(0) - 65 + 10
|
||||
else if (c >= "a" && c <= "z") d = c.charCodeAt(0) - 97 + 10
|
||||
else if (c >= "0" && c <= "9") d = +c
|
||||
total += d * chars ** (-i)
|
||||
}
|
||||
return total
|
||||
} else {
|
||||
return -this.timeline.latest
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
let name = this.data.state.events.find(e => e.type === "m.room.name")
|
||||
if (name) {
|
||||
|
@ -102,9 +123,17 @@ class Room extends ElemJS {
|
|||
return store.directs.has(this.id)
|
||||
}
|
||||
|
||||
setGroup(id) {
|
||||
this.group = id
|
||||
}
|
||||
|
||||
getGroup() {
|
||||
if (this.group) {
|
||||
return store.groups.get(this.group).value()
|
||||
} else {
|
||||
return this.isDirect() ? store.groups.get("directs").value() : store.groups.get("channels").value()
|
||||
}
|
||||
}
|
||||
|
||||
onClick() {
|
||||
store.activeRoom.set(this)
|
||||
|
@ -138,10 +167,16 @@ class Rooms extends ElemJS {
|
|||
// store.rooms.subscribe("changeItem", this.render.bind(this))
|
||||
store.activeGroup.subscribe("changeSelf", this.render.bind(this))
|
||||
store.directs.subscribe("changeItem", this.render.bind(this))
|
||||
store.newEvents.subscribe("changeSelf", this.sort.bind(this))
|
||||
|
||||
this.render()
|
||||
}
|
||||
|
||||
sort() {
|
||||
store.rooms.sort()
|
||||
this.render()
|
||||
}
|
||||
|
||||
askAdd(event, {key, data}) {
|
||||
const room = new Room(key, data)
|
||||
store.rooms.addEnd(key, room)
|
||||
|
@ -181,74 +216,20 @@ class Groups extends ElemJS {
|
|||
super(q("#c-groups-list"))
|
||||
|
||||
store.groups.subscribe("askAdd", this.askAdd.bind(this))
|
||||
store.groups.subscribe("addItem", this.addItem.bind(this))
|
||||
store.groups.subscribe("changeItem", this.render.bind(this))
|
||||
}
|
||||
|
||||
askAdd(event, {key, data}) {
|
||||
const group = new Group(key, data)
|
||||
store.groups.addEnd(key, group)
|
||||
store.groups.sort()
|
||||
}
|
||||
|
||||
addItem(event, key) {
|
||||
this.child(store.groups.get(key).value())
|
||||
render() {
|
||||
this.clearChildren()
|
||||
store.groups.forEach((key, item) => {
|
||||
this.child(item.value())
|
||||
})
|
||||
}
|
||||
}
|
||||
const groups = new Groups()
|
||||
|
||||
|
||||
;[
|
||||
{
|
||||
id: "directs",
|
||||
name: "Directs",
|
||||
icon: "/static/directs.svg"
|
||||
},
|
||||
{
|
||||
id: "channels",
|
||||
name: "Channels",
|
||||
icon: "/static/channels.svg"
|
||||
}/*,
|
||||
{
|
||||
id: "123",
|
||||
name: "Fediverse Drama Museum"
|
||||
},
|
||||
{
|
||||
id: "456",
|
||||
name: "Epicord"
|
||||
},
|
||||
{
|
||||
id: "789",
|
||||
name: "Invidious"
|
||||
}*/
|
||||
].forEach(data => store.groups.askAdd(data.id, data))
|
||||
|
||||
/*
|
||||
;[
|
||||
{id: "001", name: "riley", group: store.groups.get("directs").value()},
|
||||
{id: "002", name: "BadAtNames", group: store.groups.get("directs").value()},
|
||||
{id: "003", name: "lynxano", group: store.groups.get("directs").value()},
|
||||
{id: "004", name: "quarky", group: store.groups.get("directs").value()},
|
||||
{id: "005", name: "lepton", group: store.groups.get("directs").value()},
|
||||
{id: "006", name: "ash", group: store.groups.get("directs").value()},
|
||||
{id: "007", name: "mewmew", group: store.groups.get("directs").value()},
|
||||
{id: "008", name: "Toniob", group: store.groups.get("directs").value()},
|
||||
{id: "009", name: "cockandball", group: store.groups.get("directs").value()},
|
||||
{id: "010", name: "Carbon brainstorming", group: store.groups.get("channels").value()},
|
||||
{id: "011", name: "Bibliogram", group: store.groups.get("channels").value()},
|
||||
{id: "012", name: "Monsters Inc Debate Hall", group: store.groups.get("channels").value()},
|
||||
{id: "013", name: "DRB clan", group: store.groups.get("channels").value()},
|
||||
{id: "014", name: "mettaton simp zone", group: store.groups.get("channels").value()},
|
||||
{id: "015", name: "witches", group: store.groups.get("123").value()},
|
||||
{id: "016", name: "snouts", group: store.groups.get("123").value()},
|
||||
{id: "017", name: "monads", group: store.groups.get("123").value()},
|
||||
{id: "018", name: "radical", group: store.groups.get("123").value()},
|
||||
{id: "019", name: "blobcat", group: store.groups.get("123").value()},
|
||||
{id: "020", name: "main", group: store.groups.get("456").value()},
|
||||
{id: "021", name: "gaming", group: store.groups.get("456").value()},
|
||||
{id: "022", name: "inhalers", group: store.groups.get("456").value()},
|
||||
{id: "023", name: "minecraft", group: store.groups.get("456").value()},
|
||||
{id: "024", name: "osu", group: store.groups.get("456").value()},
|
||||
{id: "025", name: "covid", group: store.groups.get("456").value()}
|
||||
].forEach(data => store.rooms.askAdd(data.id, data))
|
||||
*/
|
||||
|
||||
store.activeGroup.set(store.groups.get("directs").value())
|
||||
|
|
|
@ -53,6 +53,16 @@ class SubscribeMapList extends Subscribable {
|
|||
this._add(key, value, false)
|
||||
}
|
||||
|
||||
sort() {
|
||||
console.log("sorting")
|
||||
this.list.sort((a, b) => {
|
||||
const orderA = this.map.get(a).value().order
|
||||
const orderB = this.map.get(b).value().order
|
||||
return orderA - orderB
|
||||
})
|
||||
this.broadcast("changeItem")
|
||||
}
|
||||
|
||||
_add(key, value, start) {
|
||||
let s
|
||||
if (this.map.has(key)) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {Subscribable} from "./Subscribable.js"
|
||||
import {SubscribeMapList} from "./SubscribeMapList.js"
|
||||
import {SubscribeSet} from "./SubscribeSet.js"
|
||||
import {SubscribeValue} from "./SubscribeValue.js"
|
||||
|
@ -7,7 +8,8 @@ const store = {
|
|||
rooms: new SubscribeMapList(SubscribeValue),
|
||||
directs: new SubscribeSet(),
|
||||
activeGroup: new SubscribeValue(),
|
||||
activeRoom: new SubscribeValue()
|
||||
activeRoom: new SubscribeValue(),
|
||||
newEvents: new Subscribable()
|
||||
}
|
||||
|
||||
window.store = store
|
||||
|
|
|
@ -3,6 +3,16 @@ import * as lsm from "../lsm.js"
|
|||
|
||||
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() {
|
||||
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`)
|
||||
url.searchParams.append("access_token", lsm.get("access_token"))
|
||||
|
@ -35,6 +45,8 @@ function sync() {
|
|||
|
||||
function manageSync(root) {
|
||||
try {
|
||||
let newEvents = false
|
||||
|
||||
// set up directs
|
||||
const directs = root.account_data.events.find(e => e.type === "m.direct")
|
||||
if (directs) {
|
||||
|
@ -49,8 +61,45 @@ function manageSync(root) {
|
|||
store.rooms.askAdd(id, room)
|
||||
}
|
||||
const timeline = store.rooms.get(id).value().timeline
|
||||
if (room.timeline.events.length) newEvents = true
|
||||
timeline.updateEvents(room.timeline.events)
|
||||
})
|
||||
|
||||
// set up groups
|
||||
Promise.all(
|
||||
Object.keys(root.groups.join).map(id => {
|
||||
if (!store.groups.has(id)) {
|
||||
return Promise.all(["profile", "rooms"].map(path => {
|
||||
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/groups/${id}/${path}`)
|
||||
url.searchParams.append("access_token", lsm.get("access_token"))
|
||||
return fetch(url.toString()).then(res => res.json())
|
||||
})).then(([profile, rooms]) => {
|
||||
rooms = rooms.chunk
|
||||
let order = 999
|
||||
let orderEvent = root.account_data.events.find(e => e.type === "im.vector.web.tag_ordering")
|
||||
if (orderEvent) {
|
||||
if (orderEvent.content.tags.includes(id)) {
|
||||
order = orderEvent.content.tags.indexOf(id)
|
||||
}
|
||||
}
|
||||
const data = {
|
||||
name: profile.name,
|
||||
icon: resolveMxc(profile.avatar_url, 96, "crop"),
|
||||
order
|
||||
}
|
||||
store.groups.askAdd(id, data)
|
||||
rooms.forEach(groupRoom => {
|
||||
if (store.rooms.has(groupRoom.room_id)) {
|
||||
store.rooms.get(groupRoom.room_id).value().setGroup(id)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
).then(() => {
|
||||
store.rooms.sort()
|
||||
})
|
||||
if (newEvents) store.newEvents.broadcast("changeSelf")
|
||||
} catch (e) {
|
||||
console.error(root)
|
||||
throw e
|
||||
|
@ -61,4 +110,21 @@ function syncLoop() {
|
|||
return sync().then(manageSync).then(syncLoop)
|
||||
}
|
||||
|
||||
;[
|
||||
{
|
||||
id: "directs",
|
||||
name: "Directs",
|
||||
icon: "/static/directs.svg",
|
||||
order: -2
|
||||
},
|
||||
{
|
||||
id: "channels",
|
||||
name: "Channels",
|
||||
icon: "/static/channels.svg",
|
||||
order: -1
|
||||
}
|
||||
].forEach(data => store.groups.askAdd(data.id, data))
|
||||
|
||||
store.activeGroup.set(store.groups.get("directs").value())
|
||||
|
||||
syncLoop()
|
||||
|
|
5
spec.js
5
spec.js
|
@ -69,6 +69,11 @@ module.exports = [
|
|||
source: "/js/Timeline.js",
|
||||
target: "/static/Timeline.js"
|
||||
},
|
||||
{
|
||||
type: "js",
|
||||
source: "/js/Anchor.js",
|
||||
target: "/static/Anchor.js"
|
||||
},
|
||||
{
|
||||
type: "js",
|
||||
source: "/js/chat.js",
|
||||
|
|
|
@ -7,7 +7,7 @@ class Anchor extends ElemJS {
|
|||
}
|
||||
|
||||
scroll() {
|
||||
console.log("anchor scrolled")
|
||||
// console.log("anchor scrolled")
|
||||
this.element.scrollIntoView({block: "start"})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ class EventGroup extends ElemJS {
|
|||
this.messages = ejs("div").class("c-message-group__messages").child(
|
||||
ejs("div").class("c-message-group__intro").child(
|
||||
ejs("div").class("c-message-group__name").text(this.data.sender),
|
||||
ejs("div").class("c-message-group__date").text("at 4:20 pm")
|
||||
ejs("div").class("c-message-group__date").text(this.data.origin_server_ts)
|
||||
),
|
||||
...this.list
|
||||
)
|
||||
|
@ -123,11 +123,13 @@ class Timeline extends Subscribable {
|
|||
this.list = []
|
||||
this.map = new Map()
|
||||
this.reactiveTimeline = new ReactiveTimeline([])
|
||||
this.latest = 0
|
||||
}
|
||||
|
||||
updateEvents(events) {
|
||||
this.broadcast("beforeChange")
|
||||
for (const eventData of events) {
|
||||
this.latest = Math.max(this.latest, eventData.origin_server_ts)
|
||||
if (this.map.has(eventData.event_id)) {
|
||||
this.map.get(eventData.event_id).update(eventData)
|
||||
} else {
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
import {q} from "./basic.js"
|
||||
import {store} from "./store/store.js"
|
||||
import * as lsm from "./lsm.js"
|
||||
import {chat} from "./chat.js"
|
||||
|
||||
let sentIndex = 0
|
||||
|
||||
const chat = q("#c-chat-textarea")
|
||||
const input = q("#c-chat-textarea")
|
||||
|
||||
chat.addEventListener("keydown", event => {
|
||||
input.addEventListener("keydown", event => {
|
||||
if (event.key === "Enter" && !event.shiftKey && !event.ctrlKey) {
|
||||
event.preventDefault()
|
||||
const body = chat.value
|
||||
send(chat.value)
|
||||
chat.value = ""
|
||||
const body = input.value
|
||||
send(input.value)
|
||||
input.value = ""
|
||||
fixHeight()
|
||||
}
|
||||
})
|
||||
|
||||
chat.addEventListener("input", () => {
|
||||
input.addEventListener("input", () => {
|
||||
fixHeight()
|
||||
})
|
||||
|
||||
function fixHeight() {
|
||||
chat.style.height = "0px"
|
||||
console.log(chat.clientHeight, chat.scrollHeight)
|
||||
chat.style.height = (chat.scrollHeight + 1) + "px"
|
||||
input.style.height = "0px"
|
||||
console.log(input.clientHeight, input.scrollHeight)
|
||||
input.style.height = (input.scrollHeight + 1) + "px"
|
||||
}
|
||||
|
||||
function getTxnId() {
|
||||
|
|
|
@ -36,6 +36,7 @@ class Group extends ElemJS {
|
|||
super("div")
|
||||
|
||||
this.data = data
|
||||
this.order = this.data.order
|
||||
|
||||
this.class("c-group")
|
||||
this.child(
|
||||
|
@ -68,6 +69,7 @@ class Room extends ElemJS {
|
|||
this.id = id
|
||||
this.data = data
|
||||
this.timeline = new Timeline()
|
||||
this.group = null
|
||||
|
||||
this.class("c-room")
|
||||
|
||||
|
@ -77,6 +79,25 @@ class Room extends ElemJS {
|
|||
this.render()
|
||||
}
|
||||
|
||||
get order() {
|
||||
if (this.group) {
|
||||
let chars = 36
|
||||
let total = 0
|
||||
const name = this.getName()
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
const c = name[i]
|
||||
let d = 0
|
||||
if (c >= "A" && c <= "Z") d = c.charCodeAt(0) - 65 + 10
|
||||
else if (c >= "a" && c <= "z") d = c.charCodeAt(0) - 97 + 10
|
||||
else if (c >= "0" && c <= "9") d = +c
|
||||
total += d * chars ** (-i)
|
||||
}
|
||||
return total
|
||||
} else {
|
||||
return -this.timeline.latest
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
let name = this.data.state.events.find(e => e.type === "m.room.name")
|
||||
if (name) {
|
||||
|
@ -102,9 +123,17 @@ class Room extends ElemJS {
|
|||
return store.directs.has(this.id)
|
||||
}
|
||||
|
||||
setGroup(id) {
|
||||
this.group = id
|
||||
}
|
||||
|
||||
getGroup() {
|
||||
if (this.group) {
|
||||
return store.groups.get(this.group).value()
|
||||
} else {
|
||||
return this.isDirect() ? store.groups.get("directs").value() : store.groups.get("channels").value()
|
||||
}
|
||||
}
|
||||
|
||||
onClick() {
|
||||
store.activeRoom.set(this)
|
||||
|
@ -138,10 +167,16 @@ class Rooms extends ElemJS {
|
|||
// store.rooms.subscribe("changeItem", this.render.bind(this))
|
||||
store.activeGroup.subscribe("changeSelf", this.render.bind(this))
|
||||
store.directs.subscribe("changeItem", this.render.bind(this))
|
||||
store.newEvents.subscribe("changeSelf", this.sort.bind(this))
|
||||
|
||||
this.render()
|
||||
}
|
||||
|
||||
sort() {
|
||||
store.rooms.sort()
|
||||
this.render()
|
||||
}
|
||||
|
||||
askAdd(event, {key, data}) {
|
||||
const room = new Room(key, data)
|
||||
store.rooms.addEnd(key, room)
|
||||
|
@ -181,74 +216,20 @@ class Groups extends ElemJS {
|
|||
super(q("#c-groups-list"))
|
||||
|
||||
store.groups.subscribe("askAdd", this.askAdd.bind(this))
|
||||
store.groups.subscribe("addItem", this.addItem.bind(this))
|
||||
store.groups.subscribe("changeItem", this.render.bind(this))
|
||||
}
|
||||
|
||||
askAdd(event, {key, data}) {
|
||||
const group = new Group(key, data)
|
||||
store.groups.addEnd(key, group)
|
||||
store.groups.sort()
|
||||
}
|
||||
|
||||
addItem(event, key) {
|
||||
this.child(store.groups.get(key).value())
|
||||
render() {
|
||||
this.clearChildren()
|
||||
store.groups.forEach((key, item) => {
|
||||
this.child(item.value())
|
||||
})
|
||||
}
|
||||
}
|
||||
const groups = new Groups()
|
||||
|
||||
|
||||
;[
|
||||
{
|
||||
id: "directs",
|
||||
name: "Directs",
|
||||
icon: "/static/directs.svg"
|
||||
},
|
||||
{
|
||||
id: "channels",
|
||||
name: "Channels",
|
||||
icon: "/static/channels.svg"
|
||||
}/*,
|
||||
{
|
||||
id: "123",
|
||||
name: "Fediverse Drama Museum"
|
||||
},
|
||||
{
|
||||
id: "456",
|
||||
name: "Epicord"
|
||||
},
|
||||
{
|
||||
id: "789",
|
||||
name: "Invidious"
|
||||
}*/
|
||||
].forEach(data => store.groups.askAdd(data.id, data))
|
||||
|
||||
/*
|
||||
;[
|
||||
{id: "001", name: "riley", group: store.groups.get("directs").value()},
|
||||
{id: "002", name: "BadAtNames", group: store.groups.get("directs").value()},
|
||||
{id: "003", name: "lynxano", group: store.groups.get("directs").value()},
|
||||
{id: "004", name: "quarky", group: store.groups.get("directs").value()},
|
||||
{id: "005", name: "lepton", group: store.groups.get("directs").value()},
|
||||
{id: "006", name: "ash", group: store.groups.get("directs").value()},
|
||||
{id: "007", name: "mewmew", group: store.groups.get("directs").value()},
|
||||
{id: "008", name: "Toniob", group: store.groups.get("directs").value()},
|
||||
{id: "009", name: "cockandball", group: store.groups.get("directs").value()},
|
||||
{id: "010", name: "Carbon brainstorming", group: store.groups.get("channels").value()},
|
||||
{id: "011", name: "Bibliogram", group: store.groups.get("channels").value()},
|
||||
{id: "012", name: "Monsters Inc Debate Hall", group: store.groups.get("channels").value()},
|
||||
{id: "013", name: "DRB clan", group: store.groups.get("channels").value()},
|
||||
{id: "014", name: "mettaton simp zone", group: store.groups.get("channels").value()},
|
||||
{id: "015", name: "witches", group: store.groups.get("123").value()},
|
||||
{id: "016", name: "snouts", group: store.groups.get("123").value()},
|
||||
{id: "017", name: "monads", group: store.groups.get("123").value()},
|
||||
{id: "018", name: "radical", group: store.groups.get("123").value()},
|
||||
{id: "019", name: "blobcat", group: store.groups.get("123").value()},
|
||||
{id: "020", name: "main", group: store.groups.get("456").value()},
|
||||
{id: "021", name: "gaming", group: store.groups.get("456").value()},
|
||||
{id: "022", name: "inhalers", group: store.groups.get("456").value()},
|
||||
{id: "023", name: "minecraft", group: store.groups.get("456").value()},
|
||||
{id: "024", name: "osu", group: store.groups.get("456").value()},
|
||||
{id: "025", name: "covid", group: store.groups.get("456").value()}
|
||||
].forEach(data => store.rooms.askAdd(data.id, data))
|
||||
*/
|
||||
|
||||
store.activeGroup.set(store.groups.get("directs").value())
|
||||
|
|
|
@ -53,6 +53,15 @@ class SubscribeMapList extends Subscribable {
|
|||
this._add(key, value, false)
|
||||
}
|
||||
|
||||
sort() {
|
||||
this.list.sort((a, b) => {
|
||||
const orderA = this.map.get(a).value().order
|
||||
const orderB = this.map.get(b).value().order
|
||||
return orderA - orderB
|
||||
})
|
||||
this.broadcast("changeItem")
|
||||
}
|
||||
|
||||
_add(key, value, start) {
|
||||
let s
|
||||
if (this.map.has(key)) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {Subscribable} from "./Subscribable.js"
|
||||
import {SubscribeMapList} from "./SubscribeMapList.js"
|
||||
import {SubscribeSet} from "./SubscribeSet.js"
|
||||
import {SubscribeValue} from "./SubscribeValue.js"
|
||||
|
@ -7,7 +8,8 @@ const store = {
|
|||
rooms: new SubscribeMapList(SubscribeValue),
|
||||
directs: new SubscribeSet(),
|
||||
activeGroup: new SubscribeValue(),
|
||||
activeRoom: new SubscribeValue()
|
||||
activeRoom: new SubscribeValue(),
|
||||
newEvents: new Subscribable()
|
||||
}
|
||||
|
||||
window.store = store
|
||||
|
|
|
@ -3,6 +3,16 @@ import * as lsm from "../lsm.js"
|
|||
|
||||
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() {
|
||||
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/sync`)
|
||||
url.searchParams.append("access_token", lsm.get("access_token"))
|
||||
|
@ -35,6 +45,8 @@ function sync() {
|
|||
|
||||
function manageSync(root) {
|
||||
try {
|
||||
let newEvents = false
|
||||
|
||||
// set up directs
|
||||
const directs = root.account_data.events.find(e => e.type === "m.direct")
|
||||
if (directs) {
|
||||
|
@ -49,8 +61,45 @@ function manageSync(root) {
|
|||
store.rooms.askAdd(id, room)
|
||||
}
|
||||
const timeline = store.rooms.get(id).value().timeline
|
||||
if (room.timeline.events.length) newEvents = true
|
||||
timeline.updateEvents(room.timeline.events)
|
||||
})
|
||||
|
||||
// set up groups
|
||||
Promise.all(
|
||||
Object.keys(root.groups.join).map(id => {
|
||||
if (!store.groups.has(id)) {
|
||||
return Promise.all(["profile", "rooms"].map(path => {
|
||||
const url = new URL(`${lsm.get("domain")}/_matrix/client/r0/groups/${id}/${path}`)
|
||||
url.searchParams.append("access_token", lsm.get("access_token"))
|
||||
return fetch(url.toString()).then(res => res.json())
|
||||
})).then(([profile, rooms]) => {
|
||||
rooms = rooms.chunk
|
||||
let order = 999
|
||||
let orderEvent = root.account_data.events.find(e => e.type === "im.vector.web.tag_ordering")
|
||||
if (orderEvent) {
|
||||
if (orderEvent.content.tags.includes(id)) {
|
||||
order = orderEvent.content.tags.indexOf(id)
|
||||
}
|
||||
}
|
||||
const data = {
|
||||
name: profile.name,
|
||||
icon: resolveMxc(profile.avatar_url, 96, "crop"),
|
||||
order
|
||||
}
|
||||
store.groups.askAdd(id, data)
|
||||
rooms.forEach(groupRoom => {
|
||||
if (store.rooms.has(groupRoom.room_id)) {
|
||||
store.rooms.get(groupRoom.room_id).value().setGroup(id)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
).then(() => {
|
||||
store.rooms.sort()
|
||||
})
|
||||
if (newEvents) store.newEvents.broadcast("changeSelf")
|
||||
} catch (e) {
|
||||
console.error(root)
|
||||
throw e
|
||||
|
@ -61,4 +110,21 @@ function syncLoop() {
|
|||
return sync().then(manageSync).then(syncLoop)
|
||||
}
|
||||
|
||||
;[
|
||||
{
|
||||
id: "directs",
|
||||
name: "Directs",
|
||||
icon: "/static/directs.svg",
|
||||
order: -2
|
||||
},
|
||||
{
|
||||
id: "channels",
|
||||
name: "Channels",
|
||||
icon: "/static/channels.svg",
|
||||
order: -1
|
||||
}
|
||||
].forEach(data => store.groups.askAdd(data.id, data))
|
||||
|
||||
store.activeGroup.set(store.groups.get("directs").value())
|
||||
|
||||
syncLoop()
|
||||
|
|
|
@ -10,7 +10,7 @@ $out-width: $base-width + rooms.$list-width
|
|||
position: relative
|
||||
width: $base-width
|
||||
flex-shrink: 0
|
||||
font-size: 24px
|
||||
font-size: 22px
|
||||
font-weight: 500
|
||||
|
||||
&__display
|
||||
|
|
Loading…
Reference in a new issue