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 = "

this is our settings dialogue

"; html += ""; html += adapters.reduce((self: string, a: Adapter) => { self += `
  • ${a.nickname}
  • ` return self; }, ""; html += ""; tabcontent.innerHTML = html; } } function addAdapter(): void { const tabcontent = $("tabcontent"); if (tabcontent) { // dropdown for protocol let html = ""; // nostr is the first protocol, so show its options by default html += "
    "; html += " "; html += " "; html += " "; html += "
    "; html += ""; html += ""; tabcontent.innerHTML = html; } } function fillAdapterProtocolOptions(): void { const proto = $("settings_newadapter_protocolselect") as HTMLSelectElement; let html = ""; switch(proto?.options[proto.selectedIndex].value) { case "nostr": html += " "; html += " "; html += " "; break; case "mastodon": case "misskey": html += " "; html += " "; html += " "; 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 { 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] = data; break; case "author": datastore[data.adapter].profileCache[data.id] = 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();