2020-10-19 08:45:17 +00:00
|
|
|
import { q, ElemJS, ejs } from "./basic.js";
|
|
|
|
import { store } from "./store/store.js";
|
|
|
|
import { Timeline } from "./Timeline.js";
|
|
|
|
import * as lsm from "./lsm.js";
|
2020-10-15 09:06:41 +00:00
|
|
|
|
|
|
|
function resolveMxc(url, size, method) {
|
2020-10-19 08:45:17 +00:00
|
|
|
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}`;
|
|
|
|
}
|
2020-10-15 09:06:41 +00:00
|
|
|
}
|
2020-10-12 12:35:54 +00:00
|
|
|
|
2020-10-12 13:26:10 +00:00
|
|
|
class ActiveGroupMarker extends ElemJS {
|
2020-10-19 08:45:17 +00:00
|
|
|
constructor() {
|
|
|
|
super(q("#c-group-marker"));
|
|
|
|
store.activeGroup.subscribe("changeSelf", this.render.bind(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
if (store.activeGroup.exists()) {
|
|
|
|
const group = store.activeGroup.value();
|
|
|
|
this.style("opacity", 1);
|
|
|
|
this.style("transform", `translateY(${group.element.offsetTop}px)`);
|
|
|
|
} else {
|
|
|
|
this.style("opacity", 0);
|
|
|
|
}
|
|
|
|
}
|
2020-10-12 13:26:10 +00:00
|
|
|
}
|
2020-10-15 03:43:37 +00:00
|
|
|
|
2020-10-19 08:45:17 +00:00
|
|
|
const activeGroupMarker = new ActiveGroupMarker();
|
2020-10-12 13:26:10 +00:00
|
|
|
|
2020-10-12 12:35:54 +00:00
|
|
|
class Group extends ElemJS {
|
2020-10-19 08:45:17 +00:00
|
|
|
constructor(key, data) {
|
|
|
|
super("div");
|
|
|
|
|
|
|
|
this.data = data;
|
|
|
|
this.order = this.data.order;
|
|
|
|
|
|
|
|
this.class("c-group");
|
|
|
|
this.child(
|
|
|
|
this.data.icon
|
|
|
|
? ejs("img").class("c-group__icon").attribute("src", this.data.icon)
|
|
|
|
: ejs("div").class("c-group__icon"),
|
|
|
|
ejs("div").class("c-group__name").text(this.data.name)
|
|
|
|
);
|
|
|
|
|
|
|
|
this.on("click", this.onClick.bind(this));
|
|
|
|
|
|
|
|
store.activeGroup.subscribe("changeSelf", this.render.bind(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const active = store.activeGroup.value() === this;
|
|
|
|
this.element.classList[active ? "add" : "remove"]("c-group--active");
|
|
|
|
}
|
|
|
|
|
|
|
|
onClick() {
|
|
|
|
store.activeGroup.set(this);
|
|
|
|
}
|
2020-10-12 12:35:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class Room extends ElemJS {
|
2020-10-19 08:45:17 +00:00
|
|
|
constructor(id, data) {
|
|
|
|
super("div");
|
|
|
|
|
|
|
|
this.id = id;
|
|
|
|
this.data = data;
|
|
|
|
this.timeline = new Timeline();
|
|
|
|
this.group = null;
|
|
|
|
|
|
|
|
this.class("c-room");
|
|
|
|
|
|
|
|
this.on("click", this.onClick.bind(this));
|
|
|
|
store.activeRoom.subscribe("changeSelf", this.render.bind(this));
|
|
|
|
|
|
|
|
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) {
|
|
|
|
name = name.content.name;
|
|
|
|
} else {
|
|
|
|
const users = this.data.summary["m.heroes"];
|
|
|
|
const usernames = users.map((u) => (u.match(/^@([^:]+):/) || [])[1] || u);
|
|
|
|
name = usernames.join(", ");
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
getIcon() {
|
|
|
|
const avatar = this.data.state.events.find(
|
|
|
|
(e) => e.type === "m.room.avatar"
|
|
|
|
);
|
|
|
|
if (avatar) {
|
|
|
|
return resolveMxc(
|
|
|
|
avatar.content.url || avatar.content.avatar_url,
|
|
|
|
32,
|
|
|
|
"crop"
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isDirect() {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
this.clearChildren();
|
|
|
|
// data
|
|
|
|
const icon = this.getIcon();
|
|
|
|
if (icon) {
|
|
|
|
this.child(ejs("img").class("c-room__icon").attribute("src", icon));
|
|
|
|
} else {
|
|
|
|
this.child(ejs("div").class("c-room__icon", "c-room__icon--no-icon"));
|
|
|
|
}
|
|
|
|
this.child(ejs("div").class("c-room__name").text(this.getName()));
|
|
|
|
// active
|
|
|
|
const active = store.activeRoom.value() === this;
|
|
|
|
this.element.classList[active ? "add" : "remove"]("c-room--active");
|
|
|
|
}
|
2020-10-12 12:35:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class Rooms extends ElemJS {
|
2020-10-19 08:45:17 +00:00
|
|
|
constructor() {
|
|
|
|
super(q("#c-rooms"));
|
|
|
|
|
|
|
|
this.roomData = [];
|
|
|
|
this.rooms = [];
|
|
|
|
|
|
|
|
store.rooms.subscribe("askAdd", this.askAdd.bind(this));
|
|
|
|
store.rooms.subscribe("addItem", this.addItem.bind(this));
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
addItem(event, key) {
|
|
|
|
const room = store.rooms.get(key).value();
|
|
|
|
if (room.getGroup() === store.activeGroup.value()) {
|
|
|
|
this.child(room);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
this.clearChildren();
|
|
|
|
let first = null;
|
|
|
|
// set room list
|
|
|
|
store.rooms.forEach((id, room) => {
|
|
|
|
if (room.value().getGroup() === store.activeGroup.value()) {
|
|
|
|
if (!first) first = room.value();
|
|
|
|
this.child(room.value());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// if needed, change the active room to be an item in the room list
|
|
|
|
if (
|
|
|
|
!store.activeRoom.exists() ||
|
|
|
|
store.activeRoom.value().getGroup() !== store.activeGroup.value()
|
|
|
|
) {
|
|
|
|
if (first) {
|
|
|
|
store.activeRoom.set(first);
|
|
|
|
} else {
|
|
|
|
store.activeRoom.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-12 12:35:54 +00:00
|
|
|
}
|
2020-10-19 08:45:17 +00:00
|
|
|
const rooms = new Rooms();
|
2020-10-12 12:35:54 +00:00
|
|
|
|
|
|
|
class Groups extends ElemJS {
|
2020-10-19 08:45:17 +00:00
|
|
|
constructor() {
|
|
|
|
super(q("#c-groups-list"));
|
|
|
|
|
|
|
|
store.groups.subscribe("askAdd", this.askAdd.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();
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
this.clearChildren();
|
|
|
|
store.groups.forEach((key, item) => {
|
|
|
|
this.child(item.value());
|
|
|
|
});
|
|
|
|
}
|
2020-10-12 12:35:54 +00:00
|
|
|
}
|
2020-10-19 08:45:17 +00:00
|
|
|
const groups = new Groups();
|