250 lines
8 KiB
TypeScript
250 lines
8 KiB
TypeScript
import {Adapter} from "./adapter";
|
|
import {Message, Attachment} from "./message"
|
|
import util from "./util"
|
|
|
|
var $ = util.$
|
|
var _ = util._
|
|
|
|
function main():void {
|
|
const settings = _("settings", JSON.parse(localStorage.getItem("settings") ?? "{}"));
|
|
const adapters = _("adapters", []);
|
|
|
|
if (settings != null) {
|
|
for (let s of settings.adapters ?? []) {
|
|
|
|
}
|
|
if (adapters.length > 0) {
|
|
_("currentAdapter", adapters[0].nickname);
|
|
// update tabbar and tabcontent with first adapter
|
|
}
|
|
} else {
|
|
console.log("no settings exist for this client");
|
|
_("settings", { adapters: [] });
|
|
showSettings();
|
|
}
|
|
registerServiceWorker();
|
|
};
|
|
|
|
async function registerServiceWorker() {
|
|
if ("serviceWorker" in navigator) {
|
|
try {
|
|
const registration = await navigator.serviceWorker.register("/serviceWorker.js", {
|
|
scope: "/",
|
|
});
|
|
if (registration.installing) {
|
|
console.log("Service worker installing");
|
|
} else if (registration.waiting) {
|
|
console.log("Service worker installed");
|
|
} else if (registration.active) {
|
|
console.log("Service worker active");
|
|
}
|
|
} catch (error) {
|
|
console.error(`Registration failed with ${error}`);
|
|
}
|
|
const registration = await navigator.serviceWorker.ready;
|
|
(registration as any).sync.register("testdata").then((r:any)=>{console.log("but i will see this!")});
|
|
}
|
|
};
|
|
|
|
|
|
function showSettings():void {
|
|
// tab bar hidden
|
|
const tabbar = $("tabbar");
|
|
if (tabbar) {
|
|
tabbar.style.display = "none";
|
|
}
|
|
|
|
// tabcontent to show settings ui
|
|
const tabcontent = $("tabcontent");
|
|
const adapters = _("adapters") as Adapter[] ?? [];
|
|
|
|
if (tabcontent) {
|
|
let html = "<p>this is our settings dialogue</p>";
|
|
html += "<button onclick='addAdapter()'>New</button>";
|
|
html += adapters.reduce((self: string, a: Adapter) => {
|
|
self += `<li><a href='#' onclick='editAdapter(${a.nickname})'>${a.nickname}</a></li>`
|
|
return self;
|
|
}, "<ul id='settings_adapterlist'>");
|
|
html += "</ul>";
|
|
html += "<button onclick='saveSettings()'>save</button>";
|
|
tabcontent.innerHTML = html;
|
|
}
|
|
}
|
|
|
|
function addAdapter(): void {
|
|
const tabcontent = $("tabcontent");
|
|
if (tabcontent) {
|
|
// dropdown for protocol
|
|
let html = "<select id='settings_newadapter_protocolselect' onchange='fillAdapterProtocolOptions()'>";
|
|
html += [ "nostr", "mastodon", "misskey" ].reduce((self, p)=>{
|
|
self += `<option value='${p}'>${p}</option>`;
|
|
return self;
|
|
}, "");
|
|
html += "</select>";
|
|
|
|
// nostr is the first protocol, so show its options by default
|
|
html += "<div id='settings_newadapter_protocoloptions'>";
|
|
html += " <label>nickname<input id='settings_newadapter_nickname'/></label>";
|
|
html += " <label>privkey<input id='settings_newadapter_nostr_privkey'/></label>";
|
|
html += " <label>default relays<input id='settings_newadapter_nostr_default_relays'/></label>";
|
|
html += "</div>";
|
|
|
|
html += "<button onclick='saveAdapter()'>Add</button>";
|
|
html += "<button onclick='showSettings()'>Back</button>";
|
|
|
|
tabcontent.innerHTML = html;
|
|
}
|
|
}
|
|
|
|
function fillAdapterProtocolOptions(): void {
|
|
const proto = $("settings_newadapter_protocolselect") as HTMLSelectElement;
|
|
|
|
let html = "";
|
|
|
|
switch(proto?.options[proto.selectedIndex].value) {
|
|
case "nostr":
|
|
html += " <label>nickname<input id='settings_newadapter_nickname'/></label>";
|
|
html += " <label>privkey<input id='settings_newadapter_nostr_privkey'/></label>";
|
|
html += " <label>default relays<input id='settings_newadapter_nostr_default_relays'/></label>";
|
|
break;
|
|
case "mastodon":
|
|
case "misskey":
|
|
html += " <label>nickname<input id='settings_newadapter_nickname'/></label>";
|
|
html += " <label>server<input id='settings_newadapter_masto_server'/></label>";
|
|
html += " <label>API key<input id='settings_newadapter_masto_apikey'/></label>";
|
|
break;
|
|
}
|
|
|
|
|
|
const div = $("settings_newadapter_protocoloptions");
|
|
if (div) {
|
|
div.innerHTML = html;
|
|
}
|
|
}
|
|
|
|
function saveSettings(): void {
|
|
const settings = _("settings");
|
|
if (settings) {
|
|
localStorage.setItem("settings", JSON.stringify(settings));
|
|
}
|
|
// tab bar hidden
|
|
const tabbar = $("tabbar");
|
|
if (tabbar) {
|
|
tabbar.style.display = "block";
|
|
}
|
|
|
|
// tabcontent to show settings ui
|
|
const tabcontent = $("tabcontent");
|
|
if (tabcontent) {
|
|
tabcontent.innerHTML = "";
|
|
}
|
|
}
|
|
|
|
function saveAdapter(): void {
|
|
let self: any = {};
|
|
// get selected adapter protocol
|
|
const proto = $("settings_newadapter_protocolselect") as HTMLSelectElement;
|
|
console.log(proto.options[proto.selectedIndex]);
|
|
|
|
|
|
const nickname = ($("settings_newadapter_nickname") as HTMLInputElement)?.value ?? "" ;
|
|
|
|
// switch protocol
|
|
switch (proto.options[proto.selectedIndex].value) {
|
|
case "nostr":
|
|
const privkey = ($("settings_newadapter_nostr_privkey") as HTMLInputElement)?.value ?? "";
|
|
const relays = ($("settings_newadapter_nostr_default_relays") as HTMLInputElement)?.value ?? "";
|
|
self = { nickname: nickname, protocol: "nostr", privkey: privkey, relays: relays.split(",").map(r=>r.trim()) };
|
|
break;
|
|
case "mastodon":
|
|
case "misskey":
|
|
const server = ($("settings_newadapter_masto_server") as HTMLInputElement)?.value ?? "";
|
|
const apiKey = ($("settings_newadapter_masto_apikey") as HTMLInputElement)?.value ?? "";
|
|
self = { nickname: nickname, protocol: proto.options[proto.selectedIndex].value, server: server, apiKey: apiKey };
|
|
break;
|
|
}
|
|
const settings = _("settings");
|
|
if (settings) {
|
|
if (!settings.adapters) {
|
|
settings.adapters = [];
|
|
}
|
|
settings.adapters.push(self);
|
|
|
|
localStorage.setItem("settings", JSON.stringify(settings));
|
|
showSettings();
|
|
}
|
|
}
|
|
|
|
|
|
let _conn: WebSocket | null = null;
|
|
|
|
async function authorizedFetch(method: string, uri: string, body: any): Promise<Response> {
|
|
const headers = new Headers()
|
|
headers.set('Authorization', 'Bearer ' + _("skey"))
|
|
return await fetch(uri, {
|
|
method: method,
|
|
headers: headers,
|
|
body: body,
|
|
})
|
|
}
|
|
|
|
function connect() {
|
|
|
|
var datastore: AdapterState = {}
|
|
datastore = _("datastore", datastore);
|
|
|
|
const wsProto = location.protocol == "https:" ? "wss" : "ws";
|
|
_conn = new WebSocket(`${wsProto}://${location.host}/subscribe`, "underbbs");
|
|
_conn.addEventListener("open", (e: any) => {
|
|
console.log("websocket connection opened");
|
|
console.log(JSON.stringify(e));
|
|
});
|
|
_conn.addEventListener("message", (e: any) => {
|
|
|
|
// debugging
|
|
console.log(e)
|
|
|
|
// now we'll figure out what to do with it
|
|
const data = JSON.parse(e.data);
|
|
if (data.key) {
|
|
_("skey", data.key)
|
|
authorizedFetch("POST", "/api/adapters", JSON.stringify(_("settings").adapters))
|
|
} else {
|
|
if (!datastore[data.adapter]) {
|
|
datastore[data.adapter] = new AdapterData(data.protocol);
|
|
}
|
|
|
|
// typeswitch on the incoming data type and fill the memory
|
|
switch (data.type) {
|
|
case "message":
|
|
datastore[data.adapter].messages[data.id] = <Message>data;
|
|
break;
|
|
case "author":
|
|
datastore[data.adapter].profileCache[data.id] = <Author>data;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// if the adapter is active, inject the web components
|
|
// FOR HOTFETCHED DATA:
|
|
// before fetching, we can set properties on the DOM,
|
|
// so when those data return to us we know where to inject components!
|
|
if (_("currentAdapter") == data.adapter) {
|
|
// dive in and insert that shit in the dom
|
|
}
|
|
}
|
|
});
|
|
_conn.addEventListener("error", (e: any) => {
|
|
console.log("websocket connection error");
|
|
console.log(JSON.stringify(e));
|
|
});
|
|
_("websocket", _conn);
|
|
}
|
|
|
|
_("addAdapter", addAdapter);
|
|
_("saveAdapter", saveAdapter);
|
|
_("fillAdapterProtocolOptions", fillAdapterProtocolOptions);
|
|
_("showSettings", showSettings);
|
|
_("saveSettings", saveSettings);
|
|
_("connect", connect);
|
|
main();
|