client.js (4857B)
1 window.BzlPluginHost.register("directory-publisher", (ctx) => { 2 ctx.devLog("info", "directory-publisher client loaded"); 3 4 let mountEl = null; 5 let config = null; 6 let lastResult = null; 7 8 const el = (tag, props = {}, children = []) => { 9 const node = document.createElement(tag); 10 for (const [k, v] of Object.entries(props || {})) { 11 if (k === "className") node.className = String(v || ""); 12 else if (k === "text") node.textContent = String(v ?? ""); 13 else if (k.startsWith("on") && typeof v === "function") node.addEventListener(k.slice(2).toLowerCase(), v); 14 else if (v === false || v == null) continue; 15 else node.setAttribute(k, String(v)); 16 } 17 for (const c of children) { 18 if (c instanceof Node) node.appendChild(c); 19 } 20 return node; 21 }; 22 23 const safe = (v) => String(v ?? ""); 24 25 function render() { 26 if (!mountEl) return; 27 mountEl.innerHTML = ""; 28 29 const c = config && typeof config === "object" ? config : {}; 30 const inst = c.instance && typeof c.instance === "object" ? c.instance : {}; 31 32 const directoryUrl = el("input", { value: safe(c.directoryUrl), placeholder: "https://chat.bzl.one" }); 33 const name = el("input", { value: safe(inst.name), placeholder: "Display name" }); 34 const description = el("input", { value: safe(inst.description), placeholder: "Short description" }); 35 const bzlVersion = el("input", { value: safe(inst.bzlVersion), placeholder: "bzl version (optional)" }); 36 const requiresReg = el("input", { type: "checkbox", checked: inst.requiresRegistrationCode ? "checked" : null }); 37 38 const statusText = 39 lastResult && typeof lastResult === "object" 40 ? lastResult.ok 41 ? `Published (HTTP ${lastResult.status || 200})` 42 : `Publish failed: ${safe(lastResult.error || lastResult.body || `HTTP ${lastResult.status || 0}`)}` 43 : ""; 44 45 const status = statusText ? el("div", { className: lastResult?.ok ? "good small" : "bad small", text: statusText, style: "margin-top:10px" }) : null; 46 47 const saveBtn = el("button", { 48 type: "button", 49 className: "primary", 50 text: "Save", 51 onclick: () => { 52 ctx.send("setConfig", { 53 config: { 54 directoryUrl: safe(directoryUrl.value).trim(), 55 instance: { 56 id: "", 57 url: window.location.origin, 58 name: safe(name.value).trim(), 59 description: safe(description.value).trim(), 60 bzlVersion: safe(bzlVersion.value).trim(), 61 requiresRegistrationCode: Boolean(requiresReg.checked), 62 }, 63 }, 64 }); 65 }, 66 }); 67 68 const publishBtn = el("button", { type: "button", className: "ghost", text: "Publish now", onclick: () => ctx.send("publishNow", {}) }); 69 70 mountEl.appendChild( 71 el("div", { className: "panel", style: "padding:12px" }, [ 72 el("div", { text: "Directory publisher", style: "font-weight:700; margin-bottom:8px" }), 73 el("div", { className: "muted small", text: "Announces this instance to a directory (owner-only)." }), 74 el("div", { className: "row", style: "gap:10px; margin-top:10px" }, [ 75 el("label", { style: "flex:1" }, [el("span", { className: "muted small", text: "Directory URL" }), directoryUrl]), 76 ]), 77 el("div", { className: "muted small", text: `Instance URL: ${window.location.origin}`, style: "margin-top:10px" }), 78 el("div", { className: "muted small", text: "Instance metadata", style: "margin-top:14px" }), 79 el("div", { className: "row", style: "gap:10px; margin-top:10px" }, [ 80 el("label", { style: "flex:1" }, [el("span", { className: "muted small", text: "Bzl instance name" }), name]), 81 el("label", { style: "flex:1" }, [el("span", { className: "muted small", text: "Bzl version" }), bzlVersion]), 82 ]), 83 el("div", { className: "row", style: "gap:10px; margin-top:10px" }, [el("label", { style: "flex:1" }, [el("span", { className: "muted small", text: "Description" }), description])] ), 84 el("label", { className: "row small", style: "gap:10px; align-items:center; margin-top:10px" }, [requiresReg, el("span", { text: "Requires registration code" })]), 85 el("div", { className: "row", style: "gap:10px; margin-top:14px" }, [saveBtn, publishBtn]), 86 ...(status ? [status] : []), 87 ]) 88 ); 89 } 90 91 ctx.on("config", (msg) => { 92 config = msg?.config || null; 93 render(); 94 }); 95 ctx.on("configSaved", () => { 96 ctx.toast("Saved", "Directory publisher config saved."); 97 }); 98 ctx.on("result", (msg) => { 99 lastResult = msg || null; 100 render(); 101 }); 102 103 ctx.ui.registerModTab({ 104 id: "directory", 105 title: "Directory publish", 106 ownerOnly: true, 107 render(mount) { 108 mountEl = mount; 109 render(); 110 ctx.send("getConfig", {}); 111 }, 112 }); 113 });