underbbs/frontend/ts/websocket.ts

141 lines
5.1 KiB
TypeScript

import util from "./util"
import {AdapterState, AdapterData} from "./adapter";
import {Message, Attachment, Author} from "./message"
import {Settings} from "./settings"
import {SettingsElement} from "./settings-element"
import {ProfileElement} from "./profile-element"
import {MessageElement} from "./message-element"
import {TimelineElement} from "./timeline-element"
import {TimelineFilterElement} from "./timeline-filter-element"
import {CreateMessageElement} from "./create-message-element"
import {NavigatorElement} from "./navigator"
export class DatagramSocket {
public static skey: string | null = null;
public static conn: WebSocket | null;
private static _gateway: string = ""
private static onOpen(e: Event) {
console.log("websocket connection opened");
console.log(JSON.stringify(e));
}
private static gatewayWithScheme(): string {
return location.protocol + "//" + DatagramSocket._gateway
}
private static onMsg(e: MessageEvent) {
const data = JSON.parse(e.data);
console.log(data);
if (data.key) {
DatagramSocket.skey = data.key;
util.authorizedFetch("POST", DatagramSocket._gateway + "/api/adapters", JSON.stringify(Settings._instance.adapters))
.then(r=> {
if (r.ok) {
// iterate through any components which might want to fetch data
const profiles = document.querySelectorAll("underbbs-profile");
profiles.forEach(p=>{
const target = p.getAttribute("data-target");
p.setAttribute("data-target", target ?? "");
});
const timelines = document.querySelectorAll("underbbs-timeline");
timelines.forEach(t=>{
const target = t.getAttribute("data-target");
t.setAttribute("data-target", target ?? "");
});
}
})
.catch(e => {
util.errMsg(e.message);
});
} else {
let store = AdapterState._instance.data.get(data.adapter);
if (!store) {
AdapterState._instance.data.set(data.adapter, new AdapterData(data.protocol));
store = AdapterState._instance.data.get(data.adapter);
}
if (store) {
// typeswitch on the incoming data type and fill the memory
switch (data.type) {
case "message":
store.messages.set(data.renoteId ?? data.id, <Message>data);
break;
case "author":
store.profileCache.set(data.id, <Author>data);
break;
default:
break;
}
}
// go through each type of component and give it the latest if it's relevant to them
let profileTargets = document.querySelectorAll(`underbbs-profile[data-adapter="${data.adapter}"][data-target="${data.id}"]`);
profileTargets.forEach(t=>{
t.setAttribute("data-latest", data.id);
});
let byAuthorTargets = document.querySelectorAll(`underbbs-author-messages[data-adapter="${data.adapter}"][data-target="${data.author}"]`);
byAuthorTargets.forEach(t=>{
t.setAttribute("data-latest", data.id);
});
if (data.renoter) {
let byAuthorTargetsForBoosts = document.querySelectorAll(`underbbs-author-messages[data-adapter="${data.adapter}"][data-target="${data.renoter}"]`);
byAuthorTargetsForBoosts.forEach(t=>{
console.log("setting renote id on data-latest")
t.setAttribute("data-latest", data.renoteId);
});
}
if (data.target) {
console.log("data has target: " + data.target);
let e = document.querySelector(`underbbs-timeline#${data.target}[data-adapter="${data.adapter}"]`);
if (e) {
e.setAttribute("data-latest", data.renoteId ?? data.id);
}
}
}
}
static connect(gateway: string): void {
DatagramSocket._gateway = gateway;
const wsProto = gateway.startsWith("https://") ? "wss" : "ws";
let wsUrl = ""
if (!gateway) {
wsUrl = `${wsProto}://${location.host}/subscribe`;
} else {
if (gateway.startsWith("https:")) {
gateway = gateway.split("https://")[1];
}
wsUrl = wsProto + "://" + gateway + "/subscribe"
}
const _conn = new WebSocket(wsUrl, "underbbs");
_conn.addEventListener("open", DatagramSocket.onOpen);
_conn.addEventListener("message", DatagramSocket.onMsg);
_conn.addEventListener("error", (e: any) => {
console.log("websocket connection error");
console.log(JSON.stringify(e));
});
DatagramSocket.conn = _conn;
}
}
function init() {
const saveData = localStorage.getItem("underbbs_settings");
Settings._instance = saveData ? JSON.parse(saveData) : new Settings();
customElements.define("underbbs-message", MessageElement);
customElements.define("underbbs-settings", SettingsElement);
customElements.define("underbbs-profile", ProfileElement);
customElements.define("underbbs-timeline", TimelineElement);
customElements.define("underbbs-timeline-filter", TimelineFilterElement);
customElements.define("underbbs-create-message", CreateMessageElement);
customElements.define("underbbs-navigator", NavigatorElement);
console.log("underbbs initialized!")
}
init();