Experiment to rebuild Diffuse using web applets.
0

Configure Feed

Select the types of activity you want to include in your feed.

1import { computed, effect, type Signal, signal } from "spellcaster"; 2import { type Props, repeat, tags, text } from "spellcaster/hyperscript.js"; 3 4import type { Server } from "./types.d.ts"; 5import { loadServers, saveServers, serverId } from "./common"; 6 7//////////////////////////////////////////// 8// UI 9//////////////////////////////////////////// 10export const [servers, setServers] = signal<Record<string, Server>>(await loadServers()); 11const [form, setForm] = signal<{ 12 api_key?: string; 13 host?: string; 14 password?: string; 15 username?: string; 16}>({}); 17 18const serversMap = computed(() => { 19 return new Map(Object.entries(servers())); 20}); 21 22effect(() => { 23 saveServers(servers()); 24}); 25 26//////////////////////////////////////////// 27// UI ~ SERVERS 28//////////////////////////////////////////// 29const Server = (server: Signal<Server>) => { 30 const onclick = () => { 31 const b = server(); 32 const id = serverId(b); 33 34 const col = { ...servers() }; 35 delete col[id]; 36 37 setServers(col); 38 }; 39 40 return tags.li({ onclick, style: "cursor: pointer" }, text(server().host)); 41}; 42 43const ServerList = computed(() => { 44 if (serversMap().size === 0) { 45 return tags.p({ id: "servers" }, [tags.small({}, text("Nothing added so far."))]); 46 } 47 48 return tags.ul({ id: "servers" }, repeat(serversMap, Server)); 49}); 50 51effect(() => { 52 document.querySelector("#servers")?.replaceWith(ServerList()); 53}); 54 55//////////////////////////////////////////// 56// UI ~ FORM 57//////////////////////////////////////////// 58function addServer(event: Event) { 59 event.preventDefault(); 60 61 const f = form(); 62 63 const server: Server = { 64 apiKey: f.api_key, 65 host: f.host?.replace(/^https?:\/\//, "").replace(/\/+$/, "") || "localhost:4533", 66 username: f.username, 67 tls: f.host?.startsWith("http://") || f.host?.startsWith("localhost") ? false : true, 68 password: f.password, 69 }; 70 71 setServers({ 72 ...servers(), 73 [serverId(server)]: server, 74 }); 75} 76 77function Form() { 78 return tags.form({ onsubmit: addServer }, [ 79 tags.fieldset({ className: "grid" }, [ 80 Input("host", "Server host", "my.opensubsonic.server:4747", { required: true }), 81 ]), 82 tags.fieldset({ className: "grid" }, [ 83 Input("username", "Server name", "username", { required: true }), 84 Input("password", "Password", "password", { required: true, type: "password" }), 85 ]), 86 tags.fieldset({ className: "grid" }, [tags.input({ type: "submit", value: "Connect" }, [])]), 87 ]); 88} 89 90function Input(name: string, label: string, placeholder: string, opts: Props = {}) { 91 return tags.label({}, [ 92 tags.span({}, [ 93 tags.span({}, text(label)), 94 tags.small({}, text("required" in opts ? "" : " (optional)")), 95 ]), 96 tags.input({ 97 ...opts, 98 name, 99 placeholder, 100 oninput: (event: InputEvent) => formInput(name, (event.target as HTMLInputElement).value), 101 }), 102 ]); 103} 104 105function formInput(name: string, value: string) { 106 setForm({ ...form(), [name]: value }); 107} 108 109// 🚀 110document.querySelector("#form")?.replaceWith(Form());